1 INTEL 80287 PROGRAMMER'S REFERENCE MANUAL 1987
3 Intel Corporation makes no warranty for the use of its products and
4 assumes no responsibility for any errors which may appear in this document
5 nor does it make a commitment to update the information contained herein.
7 Intel retains the right to make changes to these specifications at any
10 Contact your local sales office to obtain the latest specifications before
13 The following are trademarks of Intel Corporation and may only be used to
14 identify Intel Products:
16 Above, BITBUS, COMMputer, CREDIT, Data Pipeline, FASTPATH, Genius, i, î,
17 ICE, iCEL, iCS, iDBP, iDIS, I²ICE, iLBX, im, iMDDX, iMMX, Inboard, Insite,
18 Intel, intel, intelBOS, Intelevision, inteligent Identifier, inteligent
19 Programming, Intellec, Intellink, iOSP, iPDS, iPSC, iRMX, iSBC, iSBX, iSDM,
20 iSXM, KEPROM, Library Manager, MAP-NET, MCS, Megachassis, MICROMAINFRAME,
21 MULTIBUS, MULTICHANNEL, MULTIMODULE, MultiSERVER, ONCE, OpenNET, OTP,
22 PC-BUBBLE, Plug-A-Bubble, PROMPT, Promware, QUEST, QueX, Quick-Pulse
23 Programming, Ripplemode, RMX/80, RUPI, Seamless, SLD, UPI, and VLSiCEL, and
24 the combination of ICE, iCS, iRMX, iSBC, iSBX, MCS, or UPI and a numerical
27 MDS is an ordering code only and is not used as a product name or
28 trademark. MDS(R) is a registered trademark of Mohawk Data Sciences
31 *MULTIBUS is a patented Intel bus.
33 Additional copies of this manual or other Intel literature may be obtained
37 Literature Distribution
42 (c)INTEL CORPORATION 1987 CG-10/86
47 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
49 An Introduction to the 80287
50 This supplement describes the 80287 Numeric Processor Extension (NPX) for
51 the 80286 microprocessor. Below is a brief overview of 80286 concepts, along
52 with some of the nomenclature used throughout this and other Intel
57 The 80286 is a new VLSI microprocessor system with exceptional capabilities
58 for supporting large-system applications. Based on a new-generation CPU (the
59 Intel 80286), this powerful microsystem is designed to support multiuser
60 reprogrammable and real-time multitasking applications. Its dedicated system
61 support circuits simplify system hardware; sophisticated hardware and
62 software tools reduce both the time and the cost of product development.
64 The 80286 is a virtual-memory microprocessor with on-chip memory management
65 and protection. The 80286 microsystem offers a total-solution approach,
66 enabling you to develop high-speed, interactive, multiuser, multitasking‘‘
67 and multiprocessor‘‘systems more rapidly and at higher performance than ever
70 Ž Reliability and system up-time are becoming increasingly important in
71 all applications. Information must be protected from misuse or
72 accidental loss. The 80286 includes a sophisticated and flexible
73 four-level protection mechanism that isolates layers of operating
74 system programs from application programs to maintain a high degree of
77 Ž The 80286 provides 16 megabytes of physical address space to support
78 today's application requirements. This large physical memory enables
79 the 80286 to keep many large programs and data structures
80 simultaneously in memory for high-speed access.
82 Ž For applications with dynamically changing memory requirements, such
83 as multiuser business systems, the 80286 CPU provides on-chip memory
84 management and virtual memory support. On an 80286-based system, each
85 user can have up to a gigabyte (2^(30) bytes) of virtual-address space.
86 This large address space virtually eliminates restrictions on the
87 number or size of programs that may be part of the system.
89 Ž Large multiuser or real-time multitasking systems are easily supported
90 by the 80286. High-performance features, such as a very high-speed
91 task switch, fast interrupt-response time, inter-task protection, and a
92 quick and direct operating system interface, make the 80286 highly
93 suited to multiuser/multitasking applications.
95 Ž The 80286 has two operating modes: Real-Address mode and
96 Protected-Address mode. In Real-Address mode, the 80286 is fully
97 compatible with the 8086, 8088, 80186, and 80188 microprocessors; all
98 of the extensive libraries of 8086 and 8088 software execute four to
99 six times faster on the 80286, without any modification.
101 Ž In Protected-Address mode, the advanced memory management and
102 protection features of the 80286 become available, without any
103 reduction in performance. Upgrading 8086 and 8088 application programs
104 to use these new memory management and protection features usually
105 requires only reassembly or recompilation (some programs may require
106 minor modification). This compatibility between 80286 and 8086
107 processor families reduces both the time and the cost of
108 software development.
111 The Organization of This Manual
112 This manual describes the 80287 Numeric Processor Extension (NPX) for the
113 80286 microprocessor. The material in this manual is presented from the
114 perspective of software designers, both at an applications and at a systems
117 Ž Chapter One, "Overview of Numeric Processing," gives an overview of
118 the 80287 NPX and reviews the concepts of numeric computation using the
121 Ž Chapter Two, "Programming Numeric Applications," provides detailed
122 information for software designers generating applications for systems
123 containing an 80286 CPU with an 80287 NPX. The 80286/80287 instruction
124 set mnemonics are explained in detail, along with a description of
125 programming facilities for these systems. A comparative 80287
126 programming example is given.
128 Ž Chapter Three, "System-Level Numeric Programming," provides
129 information of interest to systems software writers, including details
130 of the 80287 architecture and operational characteristics.
132 Ž Chapter Four, "Numeric Programming Examples," provides several
133 detailed programming examples for the 80287, including conditional
134 branching, the conversion between floating-point values and their ASCII
135 representations, and the calculation of several trigonometric
136 functions. These examples illustrate assembly-language programming on
139 Ž Appendix A, "Machine Instruction Encoding and Decoding," gives
140 reference information on the encoding of NPX instructions.
142 Ž Appendix B, "Compatability between the 80287 NPX and the 8087,"
143 describes the differences between the 80287 and the 8087.
145 Ž Appendix C, "Implementing the IEEE P754 Standard," gives details of
146 the IEEE P754 Standard.
148 Ž The Glossary defines 80287 and floating-point terminology. Refer to
153 To best use the material in this manual, readers should be familiar with
154 the operation and architecture of 80286 systems. The following manuals
155 contain information related to the content of this supplement and of
156 interest to programmers of 80287 systems:
158 Ž Introduction to the 80286, order number 210308
160 Ž ASM286 Assembly Language Reference Manual, order number 121924
162 Ž 80286 Operating System Writer's Guide, order number 121960
164 Ž 80286 Hardware Reference Manual, order number 210760
166 Ž Microprocessor and Peripheral Handbook, order number 210844
168 Ž PL/M-286 User's Guide, order number 121945
170 Ž 80287 Support Library Reference Manual, order number 122129
172 Ž 8086 Software Toolbox Manual, order number 122203 (includes
173 information about 80287 Emulator Software)
175 Notational Conventions
176 This manual uses special notation to represent sub- and superscript
177 characters. Subscript characters are surrounded by {curly brackets}, for
178 example 10{2} = 10 base 2. Superscript characters are preceeded by a caret
179 and enclosed within (parentheses), for example 10^(3) = 10 to the third
185 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
189 Chapter 1 Overview of Numeric Processing
191 Introduction to the 80287 Numeric Processor Extension
196 Programming Interface
199 80287 Numeric Processor Architecture
200 The NPX Register Stack
204 The NPX Instruction and Data Pointers
206 Computation Fundamentals
208 Data Types and Formats
216 Special Computational Situations
217 Special Numeric Values
218 Nonnormal Real Numbers
219 Denormals and Gradual Underflow
220 Unnormals‘‘Descendents of Denormal Operands
221 Zeros and Pseudo Zeros
225 Encoding of Data Types
230 Numeric Overflow and Underflow
232 Handling Numeric Errors
233 Automatic Exception Handling
234 Software Exception Handling
236 Chapter 2 Programming Numeric Applications
238 The 80287 NPX Instruction Set
239 Compatibility with the 8087 NPX
241 Data Transfer Instructions
242 Arithmetic Instructions
243 Comparison Instructions
244 Transcendental Instructions
245 Constant Instructions
246 Processor Control Instructions
247 Instruction Set Reference Information
248 Instruction Execution Time
252 Programming Facilities
257 Records and Structures
259 Comparative Programming Example
262 Concurrent Processing with the 80287
264 Instruction Synchronization
266 Error Synchronization
267 Incorrect Error Synchronization
268 Proper Error Synchronization
270 Chapter 3 System-Level Numeric Programming
273 Processor Extension Data Channel
274 Real-Address Mode and Protected Virtual-Address Mode
275 Dedicated and Reserved I/O Locations
277 Processor Initialization and Control
278 System Initialization
279 Recognizing the 80287 NPX
280 Configuring the Numerics Environment
281 Initializing the 80287
283 Handling Numeric Processing Exceptions
284 Simultaneous Exception Response
285 Exception Recovery Examples
287 Chapter 4 Numeric Programming Examples
289 Conditional Branching Examples
291 Exception Handling Examples
293 Floating-Point to ASCII Conversion Examples
294 Function Partitioning
295 Exception Considerations
297 Description of Operation
299 Inaccuracy in Scaling
300 Avoiding Underflow and Overflow
304 Trigonometric Calculation Examples
306 Cosine Uses Sine Code
308 Appendix A Machine Instriction Encoding and Decoding
310 Appendix B Compatibility Between the 80287 NPX and the 8087
312 Appendix C Implementing The IEEE P754 Standard
314 Options implemented in the 80287
315 Areas of the Standard Implemented in Software
316 Additional Software to Meet the Standard
318 Glossary of 80287 and Floating-Point Terminology
325 1-1 Evolution and Performance of Numeric Processors
326 1-2 80287 NPX Block Diagram
327 1-3 80287 Register Set
328 1-4 80287 Status Word
329 1-5 80287 Control Word Format
330 1-6 80287 Tag Word Format
331 1-7 80287 Instruction and Data Pointer Image in Memory
332 1-8 80287 Number System
334 1-10 Projective versus Affine Closure
335 1-11 Arithmetic Example Using Infinity
337 2-1 FSAVE/FRSTOR Memory Layout
338 2-2 FSTENV/FLDENV Memory Layout
339 2-3 Sample 80287 Constants
340 2-4 Status Word RECORD Definition
341 2-5 Structure Definition
342 2-6 Sample PL/M-286 Program
343 2-7 Sample ASM286 Program
344 2-8 Instructions and Register Stack
345 2-9 Synchronizing References to Shared Data
346 2-10 Documenting Data Synchronization
347 2-11 Nonconcurrent FIST Instruction Code Macro
348 2-12 Error Synchronization Examples
350 3-1 Software Routine to Recognize the 80287
352 4-1 Conditional Branching for Compares
353 4-2 Conditional Branching for FXAM
354 4-3 Full-State Exception Handler
355 4-4 Reduced-Latency Exception Handler
356 4-5 Reentrant Exception Handler
357 4-6 Floating-Point to ASCII Conversion Routine
358 4-7 Calculating Trigonometric Functions
363 1-1 Numeric Processing Speed Comparisons
364 1-2 Numeric Data Types
365 1-3 Principal NPX Instructions
366 1-4 Interpreting the NPX Condition Codes
367 1-5 Real Number Notation
369 1-7 Denormalization Process
370 1-8 Exceptions Due to Denormal Operands
371 1-9 Unnormal Operands and Results
372 1-10 Zero Operands and Results
373 1-11 Masked Overflow Response with Directed Rounding
374 1-12 Infinity Operands and Results
375 1-13 Binary Integer Encodings
376 1-14 Packed Decimal Encodings
377 1-15 Real and Long Real Encodings
378 1-16 Temporary Real Encodings
379 1-17 Exception Conditions and Masked Responses
381 2-1 Data Transfer Instructions
382 2-2 Arithmetic Instructions
383 2-3 Basic Arithmetic Instructions and Operands
384 2-4 Condition Code Interpretation after FPREM
385 2-5 Comparison Instructions
386 2-6 Condition Code Interpretation after FCOM
387 2-7 Condition Code Interpretation after FTST
388 2-8 FXAM Condition Code Settings
389 2-9 Transcendental Instructions
390 2-10 Constant Instructions
391 2-11 Processor Control Instructions
392 2-12 Key to Operand Types
393 2-13 Execution Penalties
394 2-14 Instruction Set Reference Data
395 2-15 PL/M-286 Built-In Procedures
396 2-16 80287 Storage Allocation Directives
397 2-17 Addressing Mode Examples
399 3-1 NPX Processor State Following Initialization
400 3-2 Precedence of NPX Exceptions
402 A-1 80287 Instruction Encoding
403 A-2 Machine Instruction Decoding Guide
406 Chapter 1 Overview of Numeric Processing
408 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
410 The 80287 NPX is a high-performance numerics processing element that
411 extends the 80286 architecture by adding significant numeric capabilities
412 and direct support for floating-point, extended-integer, and BCD data types.
413 The 80286 CPU with 80287 NPX easily supports powerful and accurate numeric
414 applications through its implementation of the proposed IEEE 754 Standard
415 for Binary Floating-Point Arithmetic.
418 Introduction to the 80287 Numeric Processor Extension
419 The 80287 Numeric Processor Extension (NPX) is highly compatible with its
420 predecessor, the earlier Intel 8087 NPX.
422 The 8087 NPX was designed for use in 8086-family systems. The 8086 was the
423 first microprocessor family to partition the processing unit to permit
424 high-performance numeric capabilities. The 8087 NPX for this processor
425 family implemented a complete numeric processing environment in compliance
426 with the proposed IEEE 754 Floating-Point Standard.
428 With the 80287 Numeric Processor Extension, high-speed numeric computations
429 have been extended to 80286 high-performance multi-tasking and multi-user
430 systems. Multiple tasks using the numeric processor extension are afforded
431 the full protection of the 80286 memory management and protection features.
433 Figure 1-1 illustrates the relative performance of 8-MHz 8086/8087 and
434 80286/80287 systems in executing numerics-oriented applications.
437 Figure 1-1. Evolution and Performance of Numeric Processors
439 DOUBLE-PRECISION
\x1e ’‘‘‘‘‘‘‘‘‘‘‘‘‘“
440 WHETSTONE � � 80286/80287 �
441 PERFORMANCE � ”‘‘‘‘‘‘
\a‘‘‘‘‘‘•
453 ”‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘
\x10
460 Table 1-1 compares the execution times of several 80287 instructions with
461 the equivalent operations executed in software on an 8-MHz 80286. The
462 software equivalents are highly-optimized assembly-language procedures from
463 the 80287 emulator. As indicated in the table, the 80287 NPX provides about
464 50 to 100 times the performance of software numeric routines on the 80286
465 CPU. An 8-MHz 80287 multiplies 32-bit and 64-bit real numbers in about 11.9
466 and 16.9 microseconds, respectively. Of course, the actual performance of
467 the NPX in a given system depends on the characteristics of the individual
470 Although the performance figures shown in table 1-1 refer to operations on
471 real (floating-point) numbers, the 80287 also manipulates fixed-point binary
472 and decimal integers of up to 64 bits or 18 digits, respectively. The 80287
473 can improve the speed of multiple-precision software algorithms for integer
474 operations by 10 to 100 times.
476 Because the 80287 NPX is an extension of the 80286 CPU, no software
477 overhead is incurred in setting up the NPX for computation. The 80287 and
478 80286 processors coordinate their activities in a manner transparent to
479 software. Moreover, built-in coordination facilities allow the 80286 CPU to
480 proceed with other instructions while the 80287 NPX is simultaneously
481 executing numeric instructions. Programs can exploit this concurrency of
482 execution to further increase system performance and throughput.
485 Table 1-1. Numeric Processing Speed Comparisons
487 Approximate Performance
488 Ratios: 8 MHz 80287 to
489 8 MHz Protected Mode iAPX
490 ’‘‘‘‘‘‘ Floating-Point Instruction ‘‘‘‘‘‘‘‘‘‘‘‘“ using E80287
492 FADD ST,ST (Temp Real) Addition 1: 42
493 FDIV DWORD PTR (Single-Precision) Division 1:266
494 FXAM (Stack(0) assumed) Examine 1:139
495 FYL2X (Stack(0),(1) assumed) Logarithm 1: 99
496 FPATAN (Stack(0) assumed) Arctangent 1:153
497 F2XM1 (Stack (0) assumed) Exponentiation 1: 41
501 The 80287 NPX offers more than raw execution speed for
502 computation-intensive tasks. The 80287 brings the functionality and power
503 of accurate numeric computation into the hands of the general user.
505 Like the 8087 NPX that preceded it, the 80287 is explicitly designed to
506 deliver stable, accurate results when programmed using straightforward
507 "pencil and paper" algorithms. The IEEE 754 standard specifically addresses
508 this issue, recognizing the fundamental importance of making numeric
509 computations both easy and safe to use.
511 For example, most computers can overflow when two single-precision
512 floating-point numbers are multiplied together and then divided by a third,
513 even if the final result is a perfectly valid 32-bit number. The 80287
514 delivers the correctly rounded result. Other typical examples of
515 undesirable machine behavior in straightforward calculations occur when
516 solving for the roots of a quadratic equation:
522 for computing financial rate of return, which involves the expression:
523 (1+i)^(n). On most machines, straightforward algorithms will not deliver
524 consistently correct results (and will not indicate when they are
525 incorrect). To obtain correct results on traditional machines under all
526 conditions usually requires sophisticated numerical techniques that are
527 foreign to most programmers. General application programmers using
528 straightforward algorithms will produce much more reliable programs using
529 the 80287. This simple fact greatly reduces the software investment required
530 to develop safe, accurate computation-based products.
532 Beyond traditional numerics support for scientific applications, the 80287
533 has built-in facilities for commercial computing. It can process decimal
534 numbers of up to 18 digits without round-off errors, performing exact
535 arithmetic on integers as large as 2^(64) or 10^(18). Exact arithmetic is
536 vital in accounting applications where rounding errors may introduce
537 monetary losses that cannot be reconciled.
539 The NPX contains a number of optional facilities that can be invoked by
540 sophisticated users. These advanced features include two models of infinity,
541 directed rounding, gradual underflow, and either automatic or programmed
542 exception-handling facilities.
544 These automatic exception-handling facilities permit a high degree of
545 flexibility in numeric processing software, without burdening the
546 programmer. While performing numeric calculations, the NPX automatically
547 detects exception conditions that can potentially damage a calculation. By
548 default, on-chip exception handlers may be invoked to field these exceptions
549 so that a reasonable result is produced, and execution may proceed without
550 program interruption. Alternatively, the NPX can signal the CPU, invoking a
551 software exception handler whenever various types of exceptions are
556 The NPX's versatility and performance make it appropriate to a broad array
557 of numeric applications. In general, applications that exhibit any of the
558 following characteristics can benefit by implementing numeric processing on
561 Ž Numeric data vary over a wide range of values, or include nonintegral
564 Ž Algorithms produce very large or very small intermediate results.
566 Ž Computations must be very precise; i.e., a large number of significant
567 digits must be maintained.
569 Ž Performance requirements exceed the capacity of traditional
572 Ž Consistently safe, reliable results must be delivered using a
573 programming staff that is not expert in numerical techniques.
575 Note also that the 80287 can reduce software development costs and improve
576 the performance of systems that use not only real numbers, but operate on
577 multiprecision binary or decimal integer values as well.
579 A few examples, which show how the 80287 might be used in specific numerics
580 applications, are described below. In many cases, these types of systems
581 have been implemented in the past with minicomputers. The advent of the
582 80287 brings the size and cost savings of microprocessor technology to these
583 applications for the first time.
585 Ž Business data processing‘‘The NPX's ability to accept decimal operands
586 and produce exact decimal results of up to 18 digits greatly simplifies
587 accounting programming. Financial calculations that use power functions
588 can take advantage of the 80287's exponentiation and logarithmic
591 Ž Process control‘‘The 80287 solves dynamic range problems
592 automatically, and its extended precision allows control functions to
593 be fine-tuned for more accurate and efficient performance. Control
594 algorithms implemented with the NPX also contribute to improved
595 reliability and safety, while the 80287's speed can be exploited in
596 real-time operations.
598 Ž Computer numerical control (CNC)‘‘The 80287 can move and position
599 machine tool heads with accuracy in real-time. Axis positioning also
600 benefits from the hardware trigonometric support provided by the 80287.
602 Ž Robotics‘‘Coupling small size and modest power requirements with
603 powerful computational abilities, the NPX is ideal for on-board
604 six-axis positioning.
606 Ž Navigation‘‘Very small, lightweight, and accurate inertial guidance
607 systems can be implemented with the 80287. Its built-in trigonometric
608 functions can speed and simplify the calculation of position from
610 Ž Graphics terminals‘‘The 80287 can be used in graphics terminals to
611 locally perform many functions that normally demand the attention of a
612 main computer; these include rotation, scaling, and interpolation. By
613 also using an 82720 Graphics Display Controller to perform high speed
614 data transfers, very powerful and highly self-sufficient terminals can
615 be built from a relatively small number of 80286 family parts.
617 Ž Data acquisition‘‘The 80287 can be used to scan, scale, and reduce
618 large quantities of data as it is collected, thereby lowering storage
619 requirements and time required to process the data for analysis.
621 The preceding examples are oriented toward traditional numerics
622 applications. There are, in addition, many other types of systems that do
623 not appear to the end user as computational, but can employ the 80287 to
624 advantage. Indeed, the 80287 presents the imaginative system designer with
625 an opportunity similar to that created by the introduction of the
626 microprocessor itself. Many applications can be viewed as numerically-based
627 if sufficient computational power is available to support this view. This
628 is analogous to the thousands of successful products that have been built
629 around "buried" microprocessors, even though the products themselves bear
630 little resemblance to computers.
634 The architecture of the 80286 CPU is specifically adapted to allow easy
635 upgradability to use an 80287, simply by plugging in the 80287 NPX. For this
636 reason, designers of 80286 systems may wish to incorporate the 80287 NPX
637 into their designs in order to offer two levels of price and performance at
638 little additional cost.
640 Two features of the 80286 CPU make the design and support of upgradable
641 80286 systems particularly simple:
643 Ž The 80286 can be programmed to recognize the presence of an 80287 NPX;
644 that is, software can recognize whether it is running on an 80286 or an
647 Ž After determining whether the 80287 NPX is available, the 80286 CPU
648 can be instructed to let the NPX execute all numeric instructions. If
649 an 80287 NPX is not available, the 80286 CPU can emulate all 80287
650 numeric instructions in software. This emulation is completely
651 transparent to the application software‘‘the same object code may be
652 used by both 80286 and 80287 systems. No relinking or recompiling of
653 application software is necessary; the same code will simply execute
654 faster on the 80287 than on the 80286 system.
656 To facilitate this design of upgradable 80286 systems, Intel provides a
657 software emulator for the 80287 that provides the functional equivalent of
658 the 80287 hardware, implemented in software on the 80286. Except for
659 timing, the operation of this 80287 emulator (E80287) is the same as for
660 the 80287 NPX hardware. When the emulator is combined as part of the
661 systems software, the 80286 system with 80287 emulation and the 80286 with
662 80287 hardware are virtually indistinguishable to an application program.
663 This capability makes it easy for software developers to maintain a single
664 set of programs for both systems. System manufacturers can offer the NPX
665 as a simple plug-in performance option without necessitating any changes
666 in the user's software.
669 Programming Interface
670 The 80286/80287 pair is programmed as a single processor; all of the 80287
671 registers appear to a programmer as extensions of the basic 80286 register
672 set. The 80286 has a class of instructions known as ESCAPE instructions, all
673 having a common format. These ESC instructions are numeric instructions for
674 the 80287 NPX. These numeric instructions for the 80287 are simply encoded
675 into the instruction stream along with 80286 instructions.
677 All of the CPU memory-addressing modes may be used in programming the NPX,
678 allowing convenient access to record structures, numeric arrays, and other
679 memory-based data structures. All of the memory management and protection
680 features of the CPU are extended to the NPX as well.
682 Numeric processing in the 80287 centers around the NPX register stack.
683 Programmers can treat these eight 80-bit registers as either a fixed
684 register set, with instructions operating on explicitly-designated
685 registers, or a classical stack, with instructions operating on the top one
686 or two stack elements.
688 Internally, the 80287 holds all numbers in a uniform 80-bit temporary-real
689 format. Operands that may be represented in memory as 16-, 32-, or 64-bit
690 integers, 32-, 64-, or 80-bit floating-point numbers, or 18-digit packed BCD
691 numbers, are automatically converted into temporary-real format as they are
692 loaded into the NPX registers. Computation results are subsequently
693 converted back into one of these destination data formats when they are
694 stored into memory from the NPX registers.
696 Table 1-2 lists each of the seven data types supported by the 80287,
697 showing the data format for each type. All operands are stored in memory
698 with the least significant digits starting at the initial (lowest) memory
699 address. Numeric instructions access and store memory operands using only
700 this initial address. For maximum system performance, all operands should
701 start at even memory addresses.
703 Table 1-3 lists the 80287 instructions by class. No special programming
704 tools are necessary to use the 80287, because all of the NPX instructions
705 and data types are directly supported by the ASM286 Assembler and Intel's
706 appropriate high-level languages.
708 Software routines for the 80287 may be written in ASM286 Assembler or any
709 of the following higher-level languages:
716 In addition, all of the development tools supporting the 8086 and 8087 can
717 also be used to develop software for the 80286 and 80287 operating in
720 All of these high-level languages provide programmers with access to the
721 computational power and speed of the 80287 without requiring an
722 understanding of the architecture of the 80286 and 80287 chips. Such
723 architectural considerations as concurrency and data synchronization are
724 handled automatically by these high-level languages. For the ASM286
725 programmer, specific rules for handling these issues are discussed in a
726 later section of this supplement.
729 Table 1-2. Numeric Data Types
732 Data Type Bits Digits Approximate Range (Decimal)
735 Word integer 16 4 -32,768 ¾ X ¾ +32,767
736 Short integer 32 9 -2*10^(9) ¾ X ¾ +2*10^(9)
737 Long integer 64 18 -9*10^(18) ¾ X ¾ +9*10^(18)
738 Packed decimal 80 18 -99...99 ¾ X ¾ +99...99 (18 digits)
739 Short real 32 6-7 8.43*10^(-37) ¾ �X� ¾ 3.37*10^(38)
740 Long real 64 15-16 4.19*10^(-307) ¾ �X� ¾ 1.67*10^(308)
741 Temporary real 80 19 3.4*10^(-4932) ¾ �X� ¾ 1.2*10^(4932)
744 Table 1-3. Principal NPX Instructions
746 Class Instruction Types
748 Data Transfer Load (all data types), Store (all data types), Exchange
750 Arithmetic Add, Subtract, Multiply, Divide, Subtract Reversed, Divide
751 Reversed, Square Root, Scale, Remainder, Integer Part,
752 Change Sign, Absolute Value, Extract
754 Comparison Compare, Examine, Test
756 Transcendental Tangent, Arctangent, 2^(X) -1, Y*Log{2}(X+1), Y*Log{2}(X)
758 Constants 0, 1, Ò, Log{10}2, Log{e}2, Log{2}10, Log2{e}
760 Processor Load Control Word, Store Control Word, Store Status Word,
762 Control Load Environment, Store Environment, Save, Restore, Clear
763 Exceptions, Initialize, Set Protected Mode
767 As an extension of the 80286 processor, the 80287 is wired very much in
768 parallel with the 80286 CPU. Four special status signals, PEREQ, PEACK,
769 BUSY, and ERROR, permit the two processors to coordinate their
770 activities. The 80287 NPX also monitors the 80286 S1, S0,
771 COD/INTA, READY, HLDA, and CLK pins to monitor the execution of
772 ESC instructions (numeric instructions) by the 80286.
774 As shown in figure 1-2, the 80287 NPX is divided internally into two
775 processing elements; the Bus Interface Unit (BIU) and the Numeric Execution
776 Unit (NEU). The two units operate independently of one another: the BIU
777 receives and decodes instructions, requests operand transfers with memory,
778 and executes processor control instructions, whereas the NEU processes
779 individual numeric instructions.
781 The BIU handles all of the status and signal lines between the 80287 and
782 the 80286. The NEU executes all instructions that involve the register
783 stack. These instructions include arithmetic, logical, transcendental,
784 constant, and data transfer instructions. The data path in the NEU is 84
785 bits wide (68 fraction bits, 15 exponent bits, and a sign bit), allowing
786 internal operand transfers to be performed at very high speeds.
788 The 80287 executes a single numeric instruction at a time. Before executing
789 most ESC instructions, the 80286 tests the BUSY pin and, before initiating
790 the command, waits until the 80287 indicates that it is not busy. Once
791 initiated, the 80286 continues program execution, while the 80287 executes
792 the numeric instruction. Unlike the 8087, which required a WAIT instruction
793 to test the BUSY signal before each ESC opcode, these WAIT instructions are
794 permissible, but not necessary, in 80287 programs.
796 In all cases, a WAIT or ESC instruction should be inserted after any 80287
797 store to memory (except FSTSW or FSTCW) or load from memory (except FLDENV,
798 FLDCW, or FRSTOR) before the 80286 reads or changes the memory value.
800 When needed, all data transfers between memory and the 80287 NPX are
801 performed by the 80286 CPU, using its Processor Extension Data Channel.
802 Numeric data transfers performed by the 80286 use the same timing as any
803 other bus cycle, and all such transfers come under the supervision of the
804 80286 memory management and protection mechanisms. The 80286 Processor
805 Extension Data Channel and the hardware interface between the 80286 and
806 80287 processors are described in Chapter Six of the 80286 Hardware
809 From the programmer's perspective, the 80287 can be considered just an
810 extension of the 80286 processor. All interaction between the 80286 and the
811 80287 processors on the hardware level is handled automatically by the 80286
812 and is transparent to the software.
814 To communicate with the 80287, the 80286 uses the reserved I/O port
815 addresses 00F8H, 00FAH, and 00FCH (I/O ports numbered 00F8H through 00FFH
816 are reserved for the 80286/80287 interface). These I/O operations are
817 performed automatically by the 80286 and are distinct from I/O operations
818 that result from program I/O instructions. I/O operations resulting from
819 the execution of ESC instructions are completely transparent to software.
820 Any program may execute ESCAPE (numeric) instructions, without regard to its
821 current I/O Privilege Level (IOPL).
823 To guarantee correct operation of the 80287, programs must not perform any
824 explicit I/O operations to any of the eight ports reserved for the 80287.
825 The IOPL of the 80286 can be used to protect the integrity of 80287
826 computations in multiuser reprogrammable applications, preventing any
827 accidental or other tampering with the 80287 (see Chapter Eight of the 80286
828 Operating System Writer's Guide).
831 Figure 1-2. 80287 NPX Block Diagram
833 ’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘˜‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ “
834 BUS INTERFACE UNIT NUMERIC EXECUTION UNIT
836 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ EXPONENT BUS
\x1e \x1e FRACTION BUS
837 � � CONTROL WORD � � ’‘‘‘‘‘‘‘‘‘‘“ € € ’‘‘‘‘‘‘‘‘‘‘‘‘‘“ �
838 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘— � EXPONENT �
\x11��
\x10€INTER-€
\x11���
\x10//PROGRAMMABLE//
839 � � STATUS WORD � � � MODULE � € FACE € // SHIFTER // �
840 ”‘‘‘‘‘
\x1e‘‘‘‘‘‘‘‘• ”‘‘‘‘‘‘‘‘‘‘• €
\x11�/��
\x10€ ”‘‘‘‘‘‘‘
\x1e‘‘‘‘‘•
841 � € � ’‘‘‘‘‘‘‘‘‘‘‘‘“ € 16 €
\x11������������… �
842 € NEU � MICROCODE � 16 / €
\x11�����ƒ ’‘‘‘‘‘‘‘‘‘‘‘‘“
843 � ’‘‘‘
\x1f‘‘‘‘“INSTRUCTION�CONTROL UNIT� € / 68 „
\x10� ARITHMETIC � �
844 � ���������
\x10”‘‘‘‘‘‘‘‘‘‘‘‘•‚����‡ €
\x11������ƒ� MODULE �
845 � � DATA � � ‚�������… 16 / / 64 €”‘‘‘‘‘
\x1e‘‘‘‘‘‘• �
846 Data
\x11������
\x10� BUFFER � € ’‘‘“ € €
\x11����ƒ „������…
847 � � � ’‘‘‘�‘‘‘‘‘‘“ € � ’
\x1f“’‘‘‘‘‘
\x1f‘‘‘‘‘‘
\x1f“ € ’‘‘‘‘‘‘‘‘‘‘‘“ �
848 � �
\x11��
\x10� OPERANDS �
\x11… � �T�� �(7) „��
\x10� TEMPORARY �
849 � ”‘‘‘
\x1e‘‘‘‘• � QUEUE � � �A�� � · � REGISTERS � �
850 €
\x11‘‘‘‘‘“ ”‘‘‘�‘‘‘‘‘‘• � �G�� � · ”‘‘‘‘‘‘‘‘‘‘‘•
851 � ’‘‘‘‘‘
\x1f‘‘‘“ � � � �� REGISTER � · �
852 Status
\x11���
\x10 CONTROL � ”‘‘‘‘‘‘�‘‘‘‘‘‘‘‘‘‘• �W�� STACK �
854 Address
\x11��
\x10 UNIT � � �R�� �
855 � ”‘‘‘‘‘‘‘‘‘• �D��
\x11‘ 80 BITS ‘
\x10�(0) �
857 ” ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘™‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ •
860 80287 Numeric Processor Architecture
861 To the programmer, the 80287 NPX appears as a set of additional registers
862 complementing those of the 80286. These additional registers consist of
864 Ž Eight individually-addressable 80-bit numeric registers, organized as
867 Ž Three sixteen-bit registers containing:
872 Ž Four 16-bit registers containing the NPX instruction and data pointers
874 All of the NPX numeric instructions focus on the contents of these NPX
878 The NPX Register Stack
879 The 80287 register stack is shown in figure 1-3. Each of the eight numeric
880 registers in the 80287's register stack is 80 bits wide and is divided into
881 fields corresponding to the NPX's temporary-real data type.
883 Numeric instructions address the data registers relative to the register on
884 the top of the stack. At any point in time, this top-of-stack register is
885 indicated by the ST (Stack Top) field in the NPX status word. Load or push
886 operations decrement ST by one and load a value into the new top register.
887 A store-and-pop operation stores the value from the current ST register and
888 then increments ST by one. Like 80286 stacks in memory, the 80287 register
889 stack grows down toward lower-addressed registers.
891 Many numeric instructions have several addressing modes that permit the
892 programmer to implicitly operate on the top of the stack, or to explicitly
893 operate on specific registers relative to the ST. The ASM286 Assembler
894 supports these register addressing modes, using the expression ST(0), or
895 simply ST, to represent the current Stack Top and ST(i) to specify the ith
896 register from ST in the stack (0 ¾ i ¾ 7). For example, if ST contains 011B
897 (register 3 is the top of the stack), the following statement would add the
898 contents of the top two registers on the stack (registers 3 and 5):
902 The stack organization and top-relative addressing of the numeric registers
903 simplify subroutine programming by allowing routines to pass parameters on
904 the register stack. By using the stack to pass parameters rather than using
905 "dedicated" registers, calling routines gain more flexibility in how they
906 use the stack. As long as the stack is not full, each routine simply loads
907 the parameters onto the stack before calling a particular subroutine to
908 perform a numeric calculation. The subroutine then addresses its parameters
909 as ST, ST(1), etc., even though ST may, for example, refer to physical
910 register 3 in one invocation and physical register 5 in another.
913 Figure 1-3. 80287 Register Set
915 80287 STACK: TAG FIELD
917 R1 ‚����Ð��������Ð����������������������������������������������ƒ ‚������ƒ
918 €SIGN�EXPONENT� SIGNIFICAND € € €
919 R2 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
920 R3 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
921 R4 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
922 R5 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
923 R6 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
924 R7 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
925 R8 Ñ‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
926 „����¤��������¤����������������������������������������������… „������…
929 ‚���������������������ƒ
931 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
933 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
935 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
937 ÑINSTRUCTION POINTER‘Â
939 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
943 „���������������������…
947 The 16-bit status word shown in figure 1-4 reflects the overall state of
948 the 80287. This status word may be stored into memory using the
949 FSTSW/FNSTSW, FSTENV/FNSTENV, and FSAVE/FNSAVE instructions, and can be
950 transferred into the 80286 AX register with the FSTSW AX/FNSTSW AX
951 instructions, allowing the NPX status to be inspected by the CPU.
953 The Busy bit (bit 15) and the BUSY pin indicate whether the 80287's
954 execution unit is idle (B = 0) or is executing a numeric instruction or
955 signalling an exception (B = 1). (The instructions FNSTSW, FNSTSW AX,
956 FNSTENV, and FNSAVE do not set the Busy bit themselves, nor do they require
957 the Busy bit to be clear in order to execute.)
959 The four NPX condition code bits (C{0}-C{3}) are similar to the flags in a
960 CPU: the 80287 updates these bits to reflect the outcome of arithmetic
961 operations. The effect of these instructions on the condition code bits is
962 summarized in table 1-4. These condition code bits are used principally for
963 conditional branching. The FSTSWAX instruction stores the NPX status word
964 directly into the CPU AX register, allowing these condition codes to be
965 inspected efficiently by 80286 code.
967 Bits 12-14 of the status word point to the 80287 register that is the
968 current Stack Top (ST). The significance of the stack top has been described
969 in the section on the Register Stack.
971 Figure 1-4 shows the six error flags in bits 0-5 of the status word. Bit 7
972 is the error summary status (ES) bit. ES is set if any unmasked exception
973 bits are set, and is cleared otherwise. If this bit is set, the ERROR
974 signal is asserted. Bits 0-5 indicate whether the NPX has detected one of
975 six possible exception conditions since these status bits were last cleared
979 Table 1-4. Interpreting the NPX Condition Codes
983 Type C{3} C{2} C{1} C{0} Interpretation
986 X = value is not affected by instruction 0 ST
987 ST = Top of stack > Source or 0 (FTST)
989 X = value is not affected by instruction 1 ST
990 ST = Top of stack < Source or 0 (FTST)
992 X = value is not affected by instruction 0 ST
993 ST = Top of stack = Source or 0 (FTST)
995 X = value is not affected by instruction 1 ST
996 ST = Top of stack is not comparable
999 Q{n} = Quotient bit n following complete reduction (C{2}=0) 0 Q{0}
1000 Q{n} = Quotient bit n following complete reduction (C{2}=0) Q{2}
1001 Q{n} = Quotient bit n following complete reduction (C{2}=0) Complete reduction with three
1002 low bits of quotient in C{0},
1005 U = value is undefined following instruction 1 U
1006 U = value is undefined following instruction U
1007 U = value is undefined following instruction Incomplete Reduction
1009 Examine 0 0 0 0 Valid, positive unnormalized
1010 0 0 0 1 Invalid, positive, exponent = 0
1011 0 0 1 0 Valid, negative, unnormalized
1012 0 0 1 1 Invalid, negative, exponent = 0
1013 0 1 0 0 Valid, positive, normalized
1014 0 1 0 1 Infinity, positive
1015 0 1 1 0 Valid, negative, normalized
1016 0 1 1 1 Infinity, negative
1017 1 0 0 0 Zero, positive
1018 1 0 0 1 Empty Register
1019 1 0 1 0 Zero, negative
1020 1 0 1 1 Empty Register
1021 1 1 0 0 Invalid, positive, exponent = 0
1022 1 1 0 1 Empty Register
1023 1 1 1 0 Invalid, negative, exponent = 0
1024 1 1 1 1 Empty Register
1028 Figure 1-4. 80287 Status Word
1031 ‚�Ð��Ð���Ð��Ð��Ð��Ð��Ð�Ð��Ð��Ð��Ð��Ð��Ð��ƒ EXCEPTION FLAGS
1032 €B�C3�S T�C2�C1�C0�ES�X�PE�UE�OE�ZE�DE�IE€ (1 = EXCEPTION
1033 „Ф�ФÐÐФ�Ф�Ф�Ф�ФФ�Ф�Ф�Ф�Ф�Ф�Ð… HAS OCCURRED)
1034 � � ��� � � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘ INVALID OPERATION
1035 For definitions, see the section on exception handling.
1036 � � ��� � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘ DENORMALIZED OPERAND
1037 For definitions, see the section on exception handling.
1038 � � ��� � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ ZERO DIVIDE
1039 For definitions, see the section on exception handling.
1040 � � ��� � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ OVERFLOW
1041 For definitions, see the section on exception handling.
1042 � � ��� � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ UNDERFLOW
1043 For definitions, see the section on exception handling.
1044 � � ��� � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ PRECISION
1045 For definitions, see the section on exception handling.
1046 � � ��� � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1047 � � ��� � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ ERROR SUMMARY STATUS
1048 ES is set if any unmasked exception bit is set, cleared or otherwise.
1049 � ”‘���‘‘™‘‘™‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ CONDITION CODE
1050 See Table 1-4 for condition code interpretation.
1051 � ”™™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ STACK TOP POINTER
1053 000 = REGISTER 0 IS TOP OF STACK
1054 001 = REGISTER 1 IS TOP OF STACK
1057 111 = REGISTER 7 IS TOP OF STACK
1058 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NEU BUSY
1062 The NPX provides the programmer with several processing options, which are
1063 selected by loading a word from memory into the control word. Figure 1-5
1064 shows the format and encoding of the fields in the control word.
1066 The low-order byte of this control word configures the 80287 error and
1067 exception masking. Bits 0-5 of the control word contain individual masks for
1068 each of the six exception conditions recognized by the 80287. The high-order
1069 byte of the control word configures the 80287 processing options, including
1075 The Precision control bits (bits 8-9) can be used to set the 80287 internal
1076 operating precision at less than the default precision (64-bit significand).
1077 These control bits can be used to provide compatibility with the
1078 earlier-generation arithmetic processors having less precision than the
1079 80287, as required by the IEEE 754 standard. Setting a lower precision,
1080 however, will not affect the execution time of numeric calculations.
1082 The rounding control bits (bits 10-11) provide for directed rounding and
1083 true chop as well as the unbiased round-to-nearest-even mode specified in
1084 the IEEE 754 standard.
1086 The infinity control bit (bit 12) determines the manner in which the 80287
1087 treats the special values of infinity. Either affine closure (where positive
1088 infinity is distinct from negative infinity) or projective closure (infinity
1089 is treated as a single unsigned quantity) may be specified. These two
1090 alternative views of infinity are discussed in the section on Computation
1094 Figure 1-5. 80287 Control Word Format
1096 ‚�����Ð���Ð���Ð���Ð�Ð�Ð��Ð��Ð��Ð��Ð��Ð��ƒ
1097 €X X X�I C�R C�P C�X�X�PM�UM�OM�ZM�DM�IM€ EXCEPTION MASKS
1098 „Ð�Ð�Ф�Ð�¤Ð�ФÐ�ФФФ�Ф�Ф�Ф�Ф�Ф�Ð… (1 = EXCEPTION IS MASKED)
1099 � � � � � � � � � � � � � � � ”‘‘‘‘ INVALID OPERATION
1100 � � � � � � � � � � � � � � ”‘‘‘‘‘‘‘ DENORMALIZED OPERAND
1101 � � � � � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘ ZERO DIVIDE
1102 � � � � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘ OVERFLOW
1103 � � � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ UNDERFLOW
1104 � � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ PRECISION
1105 � � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1106 � � � � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1107 � � � � � � ”‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ PRECISION CONTROL
1109 00 = 24-BIT SIGNIFICAND
1111 10 = 53-BIT SIGNIFICAND
1112 11 = 64-BIT SIGNIFICAND
1113 � � � � ”‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ ROUNDING CONTROL
1115 00 = ROUND TO NEAREST OR EVEN
1116 01 = ROUND DOWN (TOWARD -ý)
1117 10 = ROUND UP (TOWARD +ý)
1118 11 = CHOP (TRUNCATE TOWARD ZERO)
1119 � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ INFINITY CONTROL
1120 � � � (0 = PROJECTIVE, 1 = AFFINE)
1121 ”‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1125 The tag word indicates the contents of each register in the register stack,
1126 as shown in figure 1-6. The tag word is used by the NPX itself in order to
1127 track its numeric registers and optimize performance. Programmers may use
1128 this tag information to interpret the contents of the numeric registers.
1129 The tag values are stored in the tag word corresponding to the physical
1130 registers 0-7. Programmers must use the current Stack Top (ST) pointer
1131 stored in the NPX status word to associate these tag values with the
1132 relative stack registers ST(0) through ST(7).
1135 Figure 1-6. 80287 Tag Word Format
1138 ‚��������Ð��������Ð��������Ð��������Ð��������Ð��������Ð��������Ð��������ƒ
1139 € TAG(7) � TAG(6) � TAG(5) � TAG(4) � TAG(3) � TAG(2) � TAG(1) � TAG(0) €
1140 „��������¤��������¤��������¤��������¤��������¤��������¤��������¤��������…
1142 00 = VALID; 01 = ZERO; 10 = INVALID OR INFINITY; 11 = EMPTY
1145 The NPX Instruction and Data Pointers
1146 The NPX instruction and data registers provide support for programmed
1147 exception-handlers. Whenever the 80287 executes a math instruction, the NPX
1148 internally saves the instruction address, the operand address (if present),
1149 and the instruction opcode. The 80287 FSTENV and FSAVE instructions store
1150 this data into memory, allowing exception handlers to determine the precise
1151 nature of any numeric exceptions that may be encountered.
1153 When stored in memory, the instruction and data pointers appear in one of
1154 two formats, depending on the operating mode of the 80287. Figure 1-7 shows
1155 these pointers as they are stored following an FSTENV instruction. In
1156 Real-Address mode, these values are the 20-bit physical address and 11-bit
1157 opcode formatted like the 8087. In Protected mode, these values are the
1158 32-bit virtual addresses used by the program that executed the ESC
1161 The instruction address saved in the 80287 will point to any prefixes that
1162 preceded the instruction. This is different from the 8087, for which the
1163 instruction address pointed only to the ESC instruction opcode.
1166 Figure 1-7. 80287 Instruction and Data Pointer Image in Memory
1169 ‚�������������������������������ƒ
1170 REAL MODE € CONTROL WORD € +0
1171 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1173 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1175 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1176 € INSTRUCTION POINTER(15-0) € +6
1177 Ñ‘‘‘‘‘‘‘‘‘‘˜‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1178 €INSTRUCTION� � INSTRUCTION €
1179 € POINTER �0� OPCODE € +8
1180 € (19-16) � � (10-0) €
1181 Ñ‘‘‘‘‘‘‘‘‘‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1182 € DATA POINTER(15-0) € +10
1183 Ñ‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1187 „�����������¤�������������������…
1191 ‚�������������������������������ƒ
1192 PROTECTED MODE € CONTROL WORD € +0
1193 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1195 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1197 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1199 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1201 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1202 € DATA OPERAND OFFSET € +10
1203 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1204 € DATA OPERAND SELECTOR € +12
1205 „�������������������������������…
1209 Computation Fundamentals
1210 This section covers 80287 programming concepts that are common to all
1211 applications. It describes the 80287's internal number system and the
1212 various types of numbers that can be employed in NPX programs. The most
1213 commonly used options for rounding, precision, and infinity (selected by
1214 fields in the control word) are described, with exhaustive coverage of less
1215 frequently used facilities deferred to later sections. Exception conditions
1216 that may arise during execution of NPX instructions are also described along
1217 with the options that are available for responding to these exceptions.
1221 The system of real numbers that people use for pencil and paper
1222 calculations is conceptually infinite and continuous. There is no upper or
1223 lower limit to the magnitude of the numbers one can employ in a calculation,
1224 or to the precision (number of significant digits) that the numbers can
1225 represent. When considering any real number, there is always an infinity of
1226 numbers both larger and smaller. There is also an infinity of numbers
1227 between (i.e., with more significant digits than) any two real numbers. For
1228 example, between 2.5 and 2.6 are 2.51, 2.5897, 2.500001, etc.
1230 While ideally it would be desirable for a computer to be able to operate on
1231 the entire real number system, in practice this is not possible. Computers,
1232 no matter how large, ultimately have fixed-size registers and memories that
1233 limit the system of numbers that can be accommodated. These limitations
1234 determine both the range and the precision of numbers. The result is a set
1235 of numbers that is finite and discrete, rather than infinite and continuous.
1236 This sequence is a subset of the real numbers that is designed to form a
1237 useful approximation of the real number system.
1239 Figure 1-8 superimposes the basic 80287 real number system on a real number
1240 line (decimal numbers are shown for clarity, although the 80287 actually
1241 represents numbers in binary). The dots indicate the subset of real numbers
1242 the 80287 can represent as data and final results of calculations. The
1243 80287's range is approximately ±4.19*10^(-307) to ±1.67*10^(308).
1244 Applications that are required to deal with data and final results outside
1245 this range are rare. For reference, the range of the IBM 370 is about
1246 ±0.54*10^(-78) to ±0.72*10^(76).
1248 The finite spacing in figure 1-8 illustrates that the NPX can represent a
1249 great many, but not all, of the real numbers in its range. There is always a
1250 gap between two adjacent 80287 numbers, and it is possible for the result of
1251 a calculation to fall in this space. When this occurs, the NPX rounds the
1252 true result to a number that it can represent. Thus, a real number that
1253 requires more digits than the 80287 can accommodate (e.g., a 20-digit
1254 number) is represented with some loss of accuracy. Notice also that the
1255 80287's representable numbers are not distributed evenly along the real
1256 number line. In fact, an equal number of representable numbers exists
1257 between successive powers of 2 (i.e., as many representable numbers exist
1258 between 2 and 4 as between 65,536 and 131,072). Therefore, the gaps between
1259 representable numbers are larger as the numbers increase in magnitude. All
1260 integers in the range ±2^(64) (approximately ±10^(18)), however, are exactly
1263 In its internal operations, the 80287 actually employs a number system that
1264 is a substantial superset of that shown in figure 1-8. The internal format
1265 (called temporary real) extends the 80287's range to about ±3.4*10^(-4932)
1266 to ±1.2*10^(4932), and its precision to about 19 (equivalent decimal)
1267 digits. This format is designed to provide extra range and precision for
1268 constants and intermediate results, and is not normally intended for data
1271 From a practical standpoint, the 80287's set of real numbers is
1272 sufficiently large and dense so as not to limit the vast majority of
1273 microprocessor applications. Compared to most computers, including
1274 mainframes, the NPX provides a very good approximation of the real number
1275 system. It is important to remember, however, that it is not an exact
1276 representation, and that arithmetic on real numbers is inherently
1279 Conversely, and equally important, the 80287 does perform exact arithmetic
1280 on integer operands. That is, an operation on two integers returns an exact
1281 integral result, provided that the true result is an integer and is in
1282 range. For example, 4 ÷ 2 yields an exact integer, 1 ÷ 3 does not, and
1283 2^(40) * 2^(30) + 1 does not, because the result requires greater than 64
1287 Figure 1-8. 80287 Number System
1289 |
\x11‘‘‘NEGATIVE RANGE (NORMALIZED)‘‘
\x10|
1292 ’‘‘‘˜‘‘‘˜‘“’‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘“
1293 � � � ��›››�›››�œœœ�œœœ���������
1294 ”‘‘‘™‘‘‘™‘•”‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘•
1296 � � ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1297 ”-1.67*10^(308) -4.19*10^(-307)• � ‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘ �
1298 � �������������œœœœœœœœœœœœœœ �
1299 � �������������œœœœœœœœœœœœœœ �
1300 |
\x11‘‘‘POSITIVE RANGE (NORMALIZED)‘‘
\x10| � ‘‘‘‘
\a‘‘‘‘‘‘‘
\a‘‘‘‘‘‘‘
\a‘‘‘‘‘‘ �
1302 | 1 2 3 4 5 | � �
\x11‘‘˜‘‘
\x10� �
1303 ’‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘“’‘˜‘‘‘˜‘‘‘“ � � � ” 2.00000000000000000 �
1304 ���������œœœ�œœœ�›››�›››�� � � � � � � �
1305 ”‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘•”‘™‘‘‘™‘‘‘• � � ”‘‘‘‘ (NOT REPRESENTABLE) �
1306 \x1e ”‘˜‘•
\x1e � � �
1307 � ”‘‘‘‘‘‘‘‘“ � � ”‘‘‘‘‘‘‘‘ 1.99999999999999999 �
1308 � � 1.67*10^(308)• � PRECISION: �
\x11‘‘ 18 DIGITS ‘‘
\x10� �
1309 ”4.19*10^(-307) ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1312 Data Types and Formats
1313 The 80287 recognizes seven numeric data types, divided into three classes:
1314 binary integers, packed decimal integers, and binary reals. A later section
1315 describes how these formats are stored in memory (the sign is always located
1316 in the highest-addressed byte). Figure 1-9 summarizes the format of each
1317 data type. In the figure, the most significant digits of all numbers (and
1318 fields within numbers) are the leftmost digits. Table 1-5 provides the
1319 range and number of signficant (decimal) digits that each format can
1323 Table 1-5. Real Number Notation
1325 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1326 � Notation � Value �
1327 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1328 �Ordinary Decimal � 178.125 �
1329 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1330 �Scientific Decimal � 1{
\x1e}78125E2 �
1331 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1332 �Scientific Binary � 1{
\x1e)0110010001E111 �
1333 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1334 �Scientific Binary � 1{
\x1e}0110010001E10000110 �
1335 �(Biased Exponent) � �
1336 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1337 � � Sign Biased Exponent Significand �
1338 � –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1339 �80287 Short Real � �
1340 �(Normalized) � 0 10000110
\x1e 01100100010000000000000 �
1341 � � ”‘‘‘‘1{
\x1e}(implicit) �
1342 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1345 Figure 1-9. Data Formats
1347 \x11‘‘‘‘‘‘‘‘ INCREASING SIGNIFICANCE
1349 WORD €S�MAGNITUDE€ (TWO'S
1350 INTEGER „�¤���������… COMPLEMENT)
1352 ‚�Ð����������������������ƒ
1353 SHORT €S� MAGNITUDE € (TWO'S
1354 INTEGER „�¤����������������������… COMPLEMENT)
1356 ‚�Ð������������������������������������������������ƒ
1357 LONG €S� MAGNITUDE € (TWO'S
1358 INTEGER „�¤������������������������������������������������… COMPLEMENT)
1360 ‚�Ð���Ð������������������������MAGNITUDE������������������������ƒ
1361 PACKED €S� X �d17 d16
\a \a \a d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0€
1362 DECIMAL „�¤���¤���¤���¤�����������¤���¤���¤��¤��¤��¤��¤��¤��¤��¤��¤��¤��…
1364 ‚�Ð��������Ð�������������ƒ
1365 SHORT €S� BIASED � SIGNIFICAND €
1368 Position of implicit binary point. Integer bit of significand; stored in
1369 temporary real, implicit (always 1) in short and long real ������������…
1371 ‚�Ð������������Ð����������������������������������ƒ
1372 LONG €S� BIASED � SIGNIFICAND €
1373 REAL € � EXPONENT � €
1375 Position of implicit binary point. Integer bit of significand; stored in
1376 temporary real, implicit (always 1) in short and long real ���������������������������������…
1378 ‚�Ð�������������Ð�Ð���������������������������������������������ƒ
1379 TEMPORARY €S� BIASED �1� SIGNIFICAND €
1380 REAL € � EXPONENT � � €
1382 Position of implicit binary point ��������������������������������������������…
1386 S = Sign bit (0 = positive, 1 = negative)
1387 dn = Decimal digit (two per byte)
1388 X = Bits have no significance;
1389 80287 ignores when loading, zeros when storing.
1390 Exponent Bias (normal values):
1391 Short Real: 127 (7FH)
1392 Long Real: 1023 (3FFH)
1393 Temporary Real: 16383 (3FFFH)
1397 The three binary integer formats are identical except for length, which
1398 governs the range that can be accommodated in each format. The leftmost bit
1399 is interpreted as the number's sign: 0 = positive and 1 = negative. Negative
1400 numbers are represented in standard two's complement notation (the binary
1401 integers are the only 80287 format to use two's complement). The quantity
1402 zero is represented with a positive sign (all bits are 0). The 80287 word
1403 integer format is identical to the 16-bit signed integer data type of the
1408 Decimal integers are stored in packed decimal notation, with two decimal
1409 digits "packed" into each byte, except the leftmost byte, which carries the
1410 sign bit (0 = positive, 1 = negative). Negative numbers are not stored in
1411 two's complement form and are distinguished from positive numbers only by
1412 the sign bit. The most significant digit of the number is the leftmost
1413 digit. All digits must be in the range 0H-9H.
1417 The 80287 stores real numbers in a three-field binary format that resembles
1418 scientific, or exponential, notation. The number's significant digits are
1419 held in the significand field, the exponent field locates the binary point
1420 within the significant digits (and therefore determines the number's
1421 magnitude), and the sign field indicates whether the number is positive or
1422 negative. (The exponent and significand are analogous to the terms
1423 "characteristic" and "mantissa" used to describe floating point numbers on
1424 some computers.) Negative numbers differ from positive numbers only in the
1425 sign bits of their significands.
1427 Table 1-5 shows how the real number 178.125 (decimal) is stored in the
1428 80287 short real format. The table lists a progression of equivalent
1429 notations that express the same value to show how a number can be converted
1430 from one form to another. The ASM286 and PL/M-286 language translators
1431 perform a similar process when they encounter programmer-defined real number
1432 constants. Note that not every decimal fraction has an exact binary
1433 equivalent. The decimal number 1/10, for example, cannot be expressed
1434 exactly in binary (just as the number 1/3 cannot be expressed exactly in
1435 decimal). When a translator encounters such a value, it produces a rounded
1436 binary approximation of the decimal value.
1438 The NPX usually carries the digits of the significand in normalized form.
1439 This means that, except for the value zero, the significand is an integer
1440 and a fraction as follows:
1444 where
\x1e indicates an assumed binary point. The number of fraction bits
1445 varies according to the real format: 23 for short, 52 for long, and 63 for
1446 temporary real. By normalizing real numbers so that their integer bit is
1447 always a 1, the 80287 eliminates leading zeros in small values (�X� < 1).
1448 This technique maximizes the number of significant digits that can be
1449 accommodated in a significand of a given width. Note that, in the short and
1450 long real formats, the integer bit is implicit and is not actually stored;
1451 the integer bit is physically present in the temporary real format only.
1453 If one were to examine only the signficand with its assumed binary point,
1454 all normalized real numbers would have values between 1 and 2. The exponent
1455 field locates the actual binary point in the significant digits. Just as in
1456 decimal scientific notation, a positive exponent has the effect of moving
1457 the binary point to the right, and a negative exponent effectively moves the
1458 binary point to the left, inserting leading zeros as necessary. An unbiased
1459 exponent of zero indicates that the position of the assumed binary point is
1460 also the position of the actual binary point. The exponent field, then,
1461 determines a real number's magnitude.
1463 In order to simplify comparing real numbers (e.g., for sorting), the 80287
1464 stores exponents in a biased form. This means that a constant is added to
1465 the true exponent described above. The value of this bias is different for
1466 each real format (see figure 1-9). It has been chosen so as to force the
1467 biased exponent to be a positive value. This allows two real numbers
1468 (of the same format and sign) to be compared as if they are unsigned binary
1469 integers. That is, when comparing them bitwise from left to right
1470 (beginning with the leftmost exponent bit), the first bit position that
1471 differs orders the numbers; there is no need to proceed further with the
1472 comparison. A number's true exponent can be determined simply by subtracting
1473 the bias value of its format.
1475 The short and long real formats exist in memory only. If a number in one of
1476 these formats is loaded into an 80287 register, it is automatically
1477 converted to temporary real, the format used for all internal operations.
1478 Likewise, data in registers can be converted to short or long real for
1479 storage in memory. The temporary real format may be used in memory also,
1480 typically to store intermediate results that cannot be held in registers.
1482 Most applications should use the long real form to store real number data
1483 and results; it provides sufficient range and precision to return correct
1484 results with a minimum of programmer attention. The short real format is
1485 appropriate for applications that are constrained by memory, but it should
1486 be recognized that this format provides a smaller margin of safety. It is
1487 also useful for debugging algorithms, because roundoff problems will
1488 manifest themselves more quickly in this format. The temporary real format
1489 should normally be reserved for holding intermediate results, loop
1490 accumulations, and constants. Its extra length is designed to shield final
1491 results from the effects of rounding and overflow/underflow in intermediate
1492 calculations. However, the range and precision of the long real form are
1493 adequate for most microcomputer applications.
1497 Internally, the 80287 employs three extra bits (guard, round, and sticky
1498 bits) that enable it to represent the infinitely precise true result of a
1499 computation; these bits are not accessible to programmers. Whenever the
1500 destination can represent the infinitely precise true result, the 80287
1501 delivers it. Rounding occurs in arithmetic and store operations when the
1502 format of the destination cannot exactly represent the infinitely precise
1503 true result. For example, a real number may be rounded if it is stored in a
1504 shorter real format, or in an integer format. Or, the infinitely precise
1505 true result may be rounded when it is returned to a register.
1507 The NPX has four rounding modes, selectable by the RC field in the control
1508 word (see figure 1-5). Given a true result b that cannot be represented by
1509 the target data type, the 80287 determines the two representable numbers a
1510 and c that most closely bracket b in value (a < b < c). The processor then
1511 rounds (changes) b to a or to c according to the mode selected by the RC
1512 field as shown in table 1-6. Round introduces an error in a result that is
1513 less than one unit in the last place to which the result is rounded. "Round
1514 to nearest" is the default mode and is suitable for most applications; it
1515 provides the most accurate and statistically unbiased estimate of the true
1516 result. The chop mode is provided for integer arithmetic applications.
1518 "Round up" and "round down" are termed directed rounding and can be used to
1519 implement interval arithmetic. Interval arithmetic generates a certifiable
1520 result independent of the occurrence of rounding and other errors. The upper
1521 and lower bounds of an interval may be computed by executing an algorithm
1522 twice, rounding up in one pass and down in the other.
1525 Table 1-6. Rounding Modes
1527 ’‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1528 �RC Field� Rounding Mode � Rounding Action �
1529 –‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1530 � 00 � Round to nearest � Closer to b of a or c; if equally �
1531 � � � close, select even number (the one �
1532 � � � whose least significant bit is zero). �
1534 � 01 � Round down (toward -ý) � a �
1536 � 10 � Round up (toward +ý) � c �
1538 � 11 � Chop (toward 0) � Smaller in magnitude of a or c �
1539 ”‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1541 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
1543 a < b < c; a and c are representable, b is not.
1544 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
1548 The 80287 allows results to be calculated with either 64, 53, or 24 bits of
1549 precision in the significand as selected by the precision control (PC) field
1550 of the control word. The default setting, and the one that is best suited
1551 for most applications, is the full 64 bits of significance provided by the
1552 temporary-real format. The other settings are required by the proposed IEEE
1553 standard, and are provided to obtain compatibility with the specifications
1554 of certain existing programming languages. Specifying less precision
1555 nullifies the advantages of the temporary real format's extended fraction
1556 length, and does not increase execution speed. When reduced precision is
1557 specified, the rounding of the fractional value clears the unused bits on
1562 The 80287's system of real numbers may be closed by either of two models of
1563 infinity. These two means of closing the number system, projective and
1564 affine closure, are illustrated schematically in figure 1-10. The setting
1565 of the IC field in the control word selects one model or the other. The
1566 default means of closure is projective, and this is recommended for most
1567 computations. When projective closure is selected, the NPX treats the
1568 special values +ý and -ý as a single unsigned infinity (similar to its
1569 treatment of signed zeros). In the affine mode the NPX respects the signs
1572 While affine mode may provide more information than projective, there are
1573 occasions when the sign may in fact represent misinformation. For example,
1574 consider an algorithm that yields an intermediate result x of +0 and -0 (the
1575 same numeric value) in different executions. If 1/x were then computed in
1576 affine mode, two entirely different values (+ý and -ý) would result from
1577 numerically identical values of x. Projective mode, on the other hand,
1578 provides less information but never returns misinformation. In general,
1579 then, projective mode should be used globally, with affine mode reserved
1580 for local computations where the programmer can take advantage of the sign
1581 and knows for certain that the nature of the computations will not produce a
1585 Figure 1-10. Projective versus Affine Closure
1587 PROJECTIVE CLOSURE AFFINE CLOSURE
1590 ’‘‘‘‘
\x10\a\x11‘‘‘‘“
1593 � �
\a\x11‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘
\x10\a
1598 Special Computational Situations
1599 Besides being able to represent positive and negative numbers, the 80287
1600 data formats may be used to describe other entities. These special values
1601 provide extra flexibility, but most users will not need to understand them
1602 in order to use the 80287 successfully. This section describes the special
1603 values that may occur in certain cases and the significance of each. The
1604 80286 exceptions are also described, for writers of exception handlers and
1605 for those interested in probing the limits of computation using the 80287.
1607 The material presented in this section is mainly of interest to programmers
1608 concerned with writing exception handlers. For many readers, this section
1609 can be browsed lightly.
1612 Special Numeric Values
1613 The 80287 data formats encompass encodings for a variety of special values
1614 in addition to the typical real or integer data values that result from
1615 normal calculations. These special values have significance and can express
1616 relevant information about the computations or operations that produced
1617 them. The various types of special values are
1619 Ž Non-normal real numbers, including
1623 Ž Zeros and pseudo zeros
1625 Ž Positive and negative infinity
1627 Ž NaN (Not-a-Number)
1631 The following description explains the origins and significance of each of
1632 these special values. Tables 1-12 through 1-15 at the end of this
1633 section show how each of these special values is encoded for each of the
1637 Nonnormal Real Numbers
1638 As described previously, the 80287 generally stores nonzero real numbers in
1639 normalized floating-point form; that is, the integer (leading) bit of the
1640 significand is always a 1. This bit is explicitly stored in the temporary
1641 real format, and is implicitly assumed to be a one (1{
\x1e}) in the short- and
1642 long-real formats. Since leading zeros are eliminated, normalized storage
1643 allows the maximum number of significant digits to be held in a significand
1646 When a floating-point numeric value becomes very close to zero, normalized
1647 storage cannot be used to express the value accurately. To accommodate these
1648 instances, the 80287 can store and operate on reals that are not normalized,
1649 i.e., whose significands contain one or more leading zeros. Nonnormals
1650 typically arise when the result of a calculation yields a value that is too
1651 small to be represented in normal form.
1653 Nonnormal values can exist in one of two forms:
1655 Ž The floating-point exponent may be stored at its most negative value
1658 Ž The integer bit (and perhaps other leading bits) of the significand
1659 may be zero (an Unnormal).
1661 The leading zeros of nonnormals permit smaller numbers to be represented,
1662 at the cost of some lost precision (the number of significant bits is
1663 reduced by the leading zeros). In typical algorithms, extremely small values
1664 are most likely to be generated as intermediate, rather than final results.
1665 By using the NPX's temporary real format for holding intermediate, values as
1666 small as ±3.4*10^(-4932) can be represented; this makes the occurrence of
1667 nonnormal numbers a rare phenomenon in 80287 applications. Nevertheless, the
1668 NPX can load, store, and operate on nonnormalized real numbers when they do
1672 Denormals and Gradual Underflow
1673 A denormal is the result of the NPX's response to an underflow exception
1674 when that exception has been masked by the programmer (see the 80287 control
1675 word, figure 1-5). Underflow occurs when the absolute value of a real
1676 number becomes too small to be represented in the destination format, that
1677 is, when the exponent of the true result is too negative to be represented
1678 in the destination format. For example, a true exponent of -130 will cause
1679 underflow if the destination is short real, because -126 is the smallest
1680 exponent this format can accommodate. No underflow would occur if the
1681 destination were long real or temporary real, since these formats can handle
1682 exponents down to -1023 and -16,383, respectively.
1684 Most computers underflow "abruptly:" they simply return a zero result,
1685 which is likely to produce an unacceptable final result if computation
1686 continues. The 80287, on the other hand, underflows "gradually" when the
1687 underflow exception is masked. Gradual underflow is accomplished by
1688 denormalizing the result until it is just within the exponent range of the
1689 destination format. Denormalizing means incrementing the true result's
1690 exponent and inserting a corresponding leading zero in the significand,
1691 shifting the rest of the significand one place to the right. Denormal
1692 values may occur in any of the short-real, long-real, or temporary-real
1693 formats. Table 1-7 illustrates how a result might be denormalized to fit a
1694 short-real destination.
1696 The intent of the 80287's masked response to underflow is to allow
1697 computation to continue without program intervention, while introducing an
1698 error that carries about the same risk of contaminating the final result as
1699 roundoff error. Roundoff (precision) errors occur frequently in real number
1700 calculations; sometimes they spoil the result of computation, but often they
1701 do not. Recognizing that roundoff errors are often nonfatal, computation
1702 usually proceeds, and the programmer inspects the final results to see if
1703 these errors have had a significant effect. The 80287's masked underflow
1704 response allows programmers to treat underflows in a similar manner; the
1705 computation continues and the programmer can examine the final result to
1706 determine if an underflow has had important consequences. (If the underflow
1707 has had a significant effect, an invalid operation will probably be
1708 signalled later in the computation.)
1710 Denormalization produces a denormal or a zero. Denormals are readily
1711 identified by their exponents, which are always the minimum for their
1712 formats; in biased form, this is always the bit string: 00...00. This same
1713 exponent value is also assigned to the zeros, but a denormal has a nonzero
1714 significand. A denormal in a register is tagged special. Tables 1-14 and
1715 1-15 later in this chapter show how denormal values are encoded in each of
1716 the real data formats.
1718 The denormalization process may cause the loss of low-order significand
1719 bits as they are shifted off the right. In a severe case, all the
1720 significand bits of the true result are shifted out and replaced by the
1721 leading zeros. In this case, the result of denormalization is a true zero,
1722 and if the value is in a register, it is tagged as such. However, this is a
1723 comparatively rare occurrence and, in any case, is no worse than "abrupt"
1726 Denormals are rarely encountered in most applications. Typical debugged
1727 algorithms generate extremely small results during the evaluation of
1728 intermediate subexpressions; the final result is usually of an appropriate
1729 magnitude for its short or long real destination. If intermediate results
1730 are held in temporary real, as is recommended, the great range of this
1731 format makes underflow very unlikely. Denormals are likely to arise only
1732 when an application generates a great many intermediates, so many that they
1733 cannot be held on the register stack or in temporary real memory variables.
1734 If storage limitations force the use of short or long reals for
1735 intermediates, and small values are produced, underflow may occur, and, if
1736 masked, may generate denormals.
1738 Accessing a denormal may produce an exception as shown in table 1-8. (The
1739 denormalized exception signals that a denormal has been fetched.) Denormals
1740 may have reduced significance due to lost low-order bits, and an option of
1741 the proposed IEEE standard precludes operations on nonnormalized operands.
1742 This option may be implemented in the form of an exception handler that
1743 responds to unmasked denormalized exceptions. Most users will mask this
1744 exception so that computation may proceed; any loss of accuracy will be
1745 analyzed by the user when the final result is delivered.
1747 As table 1-8 shows, the division and remainder operations do not accept
1748 denormal divisors and raise the invalid operation exception. Recall also
1749 that the transcendental instructions require normalized operands and do not
1750 check for exceptions. In all other cases, the NPX converts denormals to
1751 unnormals, and the rules governing unnormal arithmetic then apply
1752 (unnormals are described in the following section).
1755 Table 1-7. Denormalization Process
1757 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1758 �Operation � Sign � Exponent
1759 Expressed as unbiased, decimal number � Significand �
1760 �‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1761 �True Result � 0 � -129 � 1{
\x1e}01011100...00 �
1762 �Denormalize � 0 � -128 � 0{
\x1e}101011100...00 �
1763 �Denormalize � 0 � -127 � 0{
\x1e}0101011100...00 �
1764 �Denormalize � 0 � -126 � 0{
\x1e}00101011100...00 �
1766 Before storing, significand is rounded to 24 bits, integer bit is
1767 dropped, and exponent is biased by adding 126 � 0 � -126 � 0{
\x1e}00101011100...00 �
1768 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1772 Table 1-8. Exceptions Due to Denormal Operands
1774 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1775 �Operation � Exception � Masked Response �
1776 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1777 �FLD (short/long real) � D � Load as equivalent unnormal �
1778 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1779 �Arithmetic (except following)� D � Convert (in a work area) �
1780 � � � denormal to equivalent �
1781 � � � unnormal and proceed �
1782 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1783 �Compare and test � D � Convert (in a work area) �
1784 � � � denormal to equivalent �
1785 � � � unnormal and proceed �
1786 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1787 �Division or FPREM with � I � Return real indefinite �
1788 �denormal divisor � � �
1789 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1792 Unnormals‘‘Descendents of Denormal Operands
1793 An unnormal is the result of a computation using denormal operands and is
1794 therefore the descendent of the 80287's masked underflow response. An
1795 unnormal may exist only in the temporary real format; it may have any
1796 exponent that a normal value may have (that is, in biased form any nonzero
1797 value), but it is distinguished from a normal by the integer bit of its
1798 significand, which is always 0. An unnormal in a register is tagged valid.
1799 Unnormals are distinct from denormals, which have an exponent of 00...00 in
1802 Unnormals allows arithmetic to continue following an underflow while still
1803 retaining their identity as numbers that may have reduced significance. That
1804 is, unnormal operands generate unnormal results, so long as their
1805 unnormality has a significant effect on the result. Unnormals are thus
1806 prevented from "masquerading" as normals, numbers that have full
1807 significance. On the other hand, if an unnormal has an insignificant effect
1808 on a calculation with a normal, the result will be normal. For example,
1809 adding a small unnormal to a large normal yields a normal result. The
1810 converse situation yields an unnormal.
1812 Table 1-9 shows how the instruction set deals with unnormal operands. Note
1813 that the unnormal may be the original operand or a temporary created by the
1814 80287 from a denormal.
1817 Table 1-9. Unnormal Operands and Results
1822 Addition/subtraction Normalization of operand with larger
1823 abosolute value determines normalization
1826 Multiplication If either operand is unnormal, result
1829 Division (unnormal dividend only) Result is unnormal.
1831 FPREM (unnormal dividend only) Result if normalized.
1833 Division/FPREM (unnormal Signal invalid operation.
1836 Compare/FTST Normalize as much as possible before
1839 FRNDINT Normalize as much as possible before
1842 FSQRT Signal invalid operation.
1844 FST, FSTP (short/long real If value is above destination's underflow
1845 destination) boundary, then signal invalid operation;
1846 else signal underflow.
1848 FSTP (temporary real destination) Store as usual.
1850 FIST, FISTP, FBSTP Signal invalid operation.
1854 FXCH Exchange as usual.
1856 Transcendental instructions Undefined; operands must be normal and
1860 Zeros and Pseudo Zeros
1861 The value zero in the real and decimal integer formats may be signed either
1862 positive or negative, although the sign of a binary integer zero is always
1863 positive. For computational purposes, the value of zero always behaves
1864 identically, regardless of sign, and typically the fact that a zero may be
1865 signed is transparent to the programmer. If necessary, the FXAM instruction
1866 may be used to determine a zero's sign.
1868 The zeros discussed above are called true zeros; if one of them is loaded
1869 or generated in a register, the register is tagged zero. Table 1-10 lists
1870 the results of instructions executed with zero operands and also shows how a
1871 true zero may be created from nonzero operands.
1873 Only the temporary real format may contain a special class of values called
1874 pseudo zeros. A pseudo zero is an unnormal whose significand is all zeros,
1875 but whose (biased) exponent is nonzero (true zeros have a zero exponent).
1876 Neither is a pseudo zero's exponent all ones, since this encoding is
1877 reserved for infinities and NANs. A pseudo zero result will be produced if
1878 two unnormals, containing a total of more than 64 leading zero bits in their
1879 significands, are multiplied together. This is a remote possibility in most
1880 applications, but it can happen.
1882 Pseudo zero operands behave like unnormals, except in the following cases
1883 where they produce the same results as true zeros:
1885 Ž Compare and test instructions
1887 Ž FRNDINT (round to integer)
1889 Ž Division, where the dividend is either a true zero or a pseudo zero
1890 (the divisor is a pseudo zero)
1892 In addition and subtraction of a pseudo zero and a true zero or another
1893 pseudo zero, the pseudo zero(s) behaves like unnormals, except for the
1894 determination of the result's sign. The sign is determined as shown in table
1895 1-10 for two true zero operands.
1899 The real formats support signed representations of infinities. These values
1900 are encoded with a biased exponent of all ones and a significand of
1901 1{
\x1e}00...00; if the infinity is in a register, it is tagged special. The
1902 significand distinguishes infinities from NANs, including real indefinite.
1904 A programmer may code an infinity, or it may be created by the NPX as its
1905 masked response to an overflow or a zero divide exception. Note that when
1906 rounding is up or down, the masked response may create the largest valid
1907 value representable in the destination rather than infinity. See table 1-11
1908 for details. As operands, infinities behave somewhat differently depending
1909 on how the infinity control field in the control word is set (see table
1910 1-12). When the projective model of infinity is selected, the infinities
1911 behave as a single unsigned representation; because of this, infinity
1912 cannot be compared with any value except infinity. In affine mode, the signs
1913 of the infinities are observed, and comparisons are possible.
1916 Table 1-10. Zero Operands and Results
1919 Operation/Operands Result Operation/Operands Result
1922 Arithmetic and compare operations with binary integers interpret the
1923 integer sign in the same manner. Division
1924 +0 +0 ±0 ÷ ±0 Invalid operation
1925 -0 -0 ±X ÷ ±0 Zerodivide
1927 Arithmetic and compare operations with binary integers interpret the
1928 integer sign in the same manner. +0 ÷ +X, -0 ÷ -X +0
1929 +0 +0 +0 ÷ -X, -0 ÷ +X -0
1930 FST, FSTP -X ÷ -Y, +X ÷ +Y +0, underflow
1931 Very small X and very large Y may yield zero, after rounding of true
1932 result. NPX signals underflow to warn that zero has been yielded from
1938 +0 +0 -X ÷ +Y, +X ÷ -Y -0, underflow
1939 Very small X and very large Y may yield zero, after rounding of true
1940 result. NPX signals underflow to warn that zero has been yielded from
1948 Severe underflows in storing to short or long real may generate zeros +0 FPREM
1950 Severe underflows in storing to short or long real may generate zeros -0 ±0 rem ±0 Invalid operation
1951 FBSTP ±X rem ±0 Invalid operation
1952 +0 +0 +0 rem +X, +0 rem -X +0
1953 -0 -0 -0 rem +X, -0 rem -X -0
1954 FIST, FISTP +X rem +Y, +X rem -Y +0
1955 When Y divides into X exactly
1960 +0 +0 -X rem -Y, -X rem +Y -0
1961 When Y divides into X exactly
1968 Small values (�X� < 1) stored into integers may round to zero +0 FSQRT
1970 Small values (�X� < 1) stored into integers may round to zero +0 -0 -0
1973 +0 plus +0 +0 Compare
1974 -0 plus -0 -0 ±0: +X A < B
1975 +0 plus -0, -0 plus +0 *0
1976 Sign is determined by round mode:
1977 * = + for nearest, up, or chop
1978 * = - for down ±0: ±0 A = B
1979 -X plus +X, +X plus -X *0
1980 Sign is determined by round mode:
1981 * = + for nearest, up, or chop
1982 * = - for down ±0: -X A > B
1983 ±0 plus ±X, ±X plus ±0 šX
1992 -0 minus +0 -0 +0 -0
1993 +0 minus +0, -0 minus -0 *0
1994 Sign is determined by round mode:
1995 * = + for nearest, up, or chop
1996 * = - for down -0 +0
1997 +X minus +X, -X minus -X *0
1998 Sign is determined by round mode:
1999 * = + for nearest, up, or chop
2001 ±0 minus ±X, ±X minus ±0 šX
2004 Multiplication +0 +0
2005 +0 * +0, -0 * -0 +0 -0 -0
2006 +0 * -0, -0 * +0 -0 FRNDINT
2007 +0 * +X, +X * +0 +0 +0 +0
2008 +0 * -X, -X * +0 -0 -0 -0
2009 -0 * +X, +X * -0 -0 FXTRACT
2010 -0 * -X, -X * -0 +0 +0 Both +0
2011 +X * +Y, -X * -Y +0, underflow
2012 Very small values of X and Y may yield zeros, after rounding of true
2013 result. NPX signals underflow to warn that zero has been yielded by
2014 nonzero operands. -0 Both -0
2015 +X * -Y, -X * +Y -0, underflow
2016 Very small values of X and Y may yield zeros, after rounding of true
2017 result. NPX signals underflow to warn that zero has been yielded by
2025 A NaN (Not a Number) is a member of a class of special values that exist in
2026 the real formats only. A NaN has an exponent of 11..11B, may have either
2027 sign, and may have any significand except 1{
\x1e}00..00B, which is assigned to
2028 the infinities. A NaN in a register is tagged special.
2030 The 80287 will generate the special NaN, real indefinite, as its masked
2031 response to an invalid operation exception. This NaN is signed negative; its
2032 significand is encoded 1{
\x1e}100..00. All other NaNs represent
2033 programmer-created values.
2035 Whenever the NPX uses an operand that is a NaN, it signals an invalid
2036 operation exception in its status word. If this exception is masked in the
2037 80287 control word, the 80287's masked exception response is to return the
2038 NaN as the operation result. If both operands of an instruction are NaNs,
2039 the result is the NaN with the larger absolute value. In this way, a NaN
2040 that enters a computation propagates through the computation and will
2041 eventually be delivered as the final result. Note, however, that the
2042 transcendental instructions do not check their operands, and a NaN will
2043 produce an undefined result.
2045 By unmasking the invalid operation exception, the programmer can use NaNs
2046 to trap to the exception handler. The generality of this approach and the
2047 large number of NaN values that are available provide the sophisticated
2048 programmer with a tool that can be applied to a variety of special
2051 For example, a compiler could use NaNs as references to uninitialized
2052 (real) array elements. The compiler could preinitialize each array element
2053 with a NaN whose significand contained the index (relative position) of the
2054 element. If an application program attempted to access an element that it
2055 had not initialized, it would use the NaN placed there by the compiler. If
2056 the invalid operation exception were unmasked, an interrupt would occur, and
2057 the exception handler would be invoked. The exception handler could
2058 determine which element had been accessed, since the operand address field
2059 of the exception pointers would point to the NaN, and the NaN would contain
2060 the index number of the array element.
2062 NaNs could also be used to speed up debugging. In its early testing phase,
2063 a program often contains multiple errors. An exception handler could be
2064 written to save diagnostic information in memory whenever it was invoked.
2065 After storing the diagnostic data, it could supply a NaN as the result of
2066 the erroneous instruction, and that NaN could point to its associated
2067 diagnostic area in memory. The program would then continue, creating a
2068 different NaN for each error. When the program ended, the NaN results could
2069 be used to access the diagnostic data saved at the time the errors
2070 occurred. Many errors could thus be diagnosed and corrected in one test run.
2073 Table 1-11. Masked Overflow Response with Directed Rounding
2075 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
2077 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘— Rounding � Result Delivered �
2078 �Normalization �Sign� Mode � �
2079 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2080 �Normal � + � Up � +ý �
2081 �Normal � + � Down � Largest finite positive number
2082 The largest valid representable reals are encoded:
2084 significand: (1){
\x1e}11...10B �
2085 �Normal � - � Up � Largest finite negative number
2086 The largest valid representable reals are encoded:
2088 significand: (1){
\x1e}11...10B �
2089 �Normal � - � Down � -ý �
2090 �Unnormal � + � Up � +ý �
2091 �Unnormal � - � Down � Largest exponent, result's significand
2092 The significand retains its identity as an unnormal; the true
2093 result is rounded as usual (effectively chopped toward 0 in this
2094 case). The exponent is encoded 11...10B. �
2095 �Unnormal � + � Up � Largest exponent, result's significand
2096 The significand retains its identity as an unnormal; the true
2097 result is rounded as usual (effectively chopped toward 0 in this
2098 case). The exponent is encoded 11...10B. �
2099 �Unnormal � - � Down � -ý �
2100 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘™‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
2103 Table 1-12. Infinity Operands and Results
2106 Key to symbols used in this table
2107 X = zero or nonzero operand
2109 * = sign of original operand
2110 š = sign is complement of original operand's sign
2111 Þ = sign is "exclusive or" original operand signs (+ if operands had
2112 same sign, - if operands had different signs)
2115 Operation Projective Result Affine Result
2118 +ý plus +ý Invalid operation +ý
2119 -ý plus -ý Invalid operation -ý
2120 +ý plus -ý Invalid operation Invalid operation
2121 -ý plus +ý Invalid operation Invalid operation
2126 +ý minus -ý Invalid operation +ý
2127 -ý minus +ý Invalid operation -ý
2128 +ý minus +ý Invalid operation Invalid operation
2129 -ý minus -ý Invalid operation Invalid operation
2136 ±0 * ±ý, ±ý * ±0 Invalid operation Invalid operation
2139 ±ý ÷ ±ý Invalid operation Invalid operation
2144 -ý Invalid operation Invalid operation
2145 +ý Invalid operation +ý
2148 ±ý rem ±ý Invalid operation Invalid operation
2149 ±ý rem ±X Invalid operation Invalid operation
2157 ±ý scaled by ±ý Invalid operation Invalid operation
2158 ±ý scaled by ±X *ý *ý
2159 ±0 scaled by ±ý *0 *0
2160 ±Y scaled by ± Invalid operation Invalid operation
2163 ±ý Invalid operation Invalid operation
2166 ±ý: ±ý A = B -ý < +ý
2167 ±ý: ±Y A ? B (and) invalid operation -ý < Y < +ý
2168 ±ý: ±0 A ? B (and) invalid operation -ý < 0 < +ý
2171 ±ý A ? B (and) invalid operation *ý
2175 For every 80287 numeric data type, one unique encoding is reserved for
2176 representing the special value indefinite. The 80287 produces this encoding
2177 as its response to a masked invalid-operation exception. In the case of
2178 reals, the indefinite value can be stored and loaded like any NaN, and it
2179 always retains its special identity; programmers are advised not to use this
2180 encoding for any other purpose. Packed decimal indefinite may be stored by
2181 the NPX in a FBSTP instruction; attempting to use this encoding in a FBLD
2182 instruction, however, will have an undefined result. In the binary
2183 integers, the same encoding may represent either indefinite or the largest
2184 negative number supported by the format (-2^(15), -2^(31), or -2^(63)). The
2185 80287 will store this encoding as its masked response to an invalid
2186 operation, or when the value in a source register represents or rounds to
2187 the largest negative integer representable by the destination. In situations
2188 where its origin may be ambiguous, the invalid operation exception flag can
2189 be examined to see if the value was produced by an exception response. When
2190 this encoding is loaded, or used by an integer arithmetic or compare
2191 operation, it is always interpreted as a negative number; thus indefinite
2192 cannot be loaded from a packed decimal or binary integer.
2195 Encoding of Data Types
2196 Tables 1-13 through 1-16 show how each of the special values just
2197 described is encoded for each of the numeric data types. In these tables,
2198 the least-significant bits are shown to the right and are stored in the
2199 lowest memory addresses. The sign bit is always the left-most bit of the
2200 highest-addressed byte.
2203 Table 1-13. Binary Integer Encodings
2205 Class Sign Magnitude
2206 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2207 � (Largest) 0 11...11
2211 � (Smallest) 0 00...01
2212 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2214 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2215 � (Smallest) 1 11...11
2219 � (Largest/Indefinite
2220 If this encoding is used as a source operand (as in an integer load or
2221 integer arithmetic instruction), the 80287 interprets it as the largest
2222 negative number representable in the format: -2^(15), -2^(31), or -2^(63).
2223 The 80287 will deliver this encoding to an integer destination in two
2225 1. If the result is the largest negative number
2226 2. As the response to a masked invalid operation exception, in which
2227 case it represents the special value integer indefinite.) 1 00...00
2228 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2230 Short: ‘‘‘31 bits‘‘‘
2234 Table 1-14. Packed Decimal Encodings
2238 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Magnitude ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
2239 Class Sign digit digit digit digit . . . digit
2240 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2241 � (Largest) 0 0000000 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 . . . 1 0 0 1
2245 � (Smallest) 0 0000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . . . 0 0 0 1
2247 � Zero 0 0000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . . . 0 0 0 0
2248 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2249 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2250 � Zero 1 0000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . . . 0 0 0 0
2252 � (Smallest) 1 0000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . . . 0 0 0 1
2256 � (Largest) 1 0000000 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 . . . 1 0 0 1
2257 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2259 The packed decimal indefinite encoding is stored by FBSTP in response to a
2260 masked invalid operation exception. Attempting to load this value via FBLD
2261 produces an undefined result. 1 1111111 1 1 1 1 1 1 1 1 U U U U
2262 UUUU means bit values are undefined and may contain any value U U U U . . . U U U U
2263 ‘‘‘‘ 1 byte ‘‘‘ ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 9 bytes ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2266 Table 1-15. Real and Long Real Encodings
2270 Integer bit is implied and not stored
2273 Class Sign Exponent {
\x1e}ff...ff
2274 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2275 � NaNs 0 11...11 11...11
2280 � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2281 � ý 0 11...11 00...00
2282 � ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2283 � � Normals 0 11...10 11...11
2287 � � 0 00...01 00...00
2288 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2289 � Reals Denormals 0 00...00 11...11
2293 � � 0 00...00 00...01
2294 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2295 � � Zero 0 00...00 00...00
2296 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2297 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2298 � � Zero 1 00...00 00...00
2299 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2300 � � Denormals 1 00...00 00...01
2304 � � 1 00...00 11...11
2305 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2306 � � Normals 1 00...01 00...00
2310 � � 1 11...10 11...11
2311 Negatives ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2312 � ý 1 11...11 00...00
2313 � ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2314 � � 1 11...11 00...01
2318 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2319 � � Indefinite 1 11...11 10...00
2320 � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2325 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2326 Short: � ‘‘‘8 bits‘‘ � ‘‘23 bits‘‘ �
2327 Long: � ‘‘11 bits‘‘ � ‘‘52 bits‘‘ �
2330 Table 1-16. Temporary Real Encodings
2334 Integer bit is implied and not stored
2337 Class Sign Exponent 1{
\x1e}ff...ff
2338 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2339 � NaNs 0 11...11 111...11
2343 � 0 11...11 100...01
2344 � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2345 � ý 0 11...11 100...00
2346 � ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2347 � � 0 11...10 Normals
2354 � � ¨ ¨ ‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2355 Positives � ¨ ¨ Unnormals
2360 � � 0 00...01 000...00
2363 � � 0 00...00 011...11
2367 � � 0 00...00 000...01
2368 � –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2369 � � Zero 0 00...00 000...00
2370 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2371 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2372 � � Zero 1 00...00 000...00
2373 � –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2375 � � 1 00...00 000...01
2379 � � 1 00...00 011...11
2381 � � 1 00...01 Unnormals
2389 Negatives � ¨ ¨ Normals
2394 � � 1 11...10 11111...11
2395 � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2396 � ý 1 11...11 100...00
2397 � ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2398 � � 1 11...11 100...00
2402 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2403 � NaNs Indefinite 1 11...11 110...00
2404 � � ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2408 � � 1 11...11 111...11
2409 ”‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2410 �‘‘15 bits‘‘�‘‘64 bits‘‘�
2414 Whenever the 80287 NPX attempts a numeric operation with invalid operands
2415 or produces a result that cannot be represented, the 80287 recognizes a
2416 numeric exception condition. Altogether, the 80287 checks for the following
2417 six classes of exceptions while executing numeric instructions:
2419 1. Invalid operation
2421 3. Denormalized operand
2423 5. Numeric underflow
2424 6. Inexact result (precision)
2428 The 80287 reports an invalid operation if any of the following occurs:
2430 Ž An attempt to load a register that is not empty (stack overflow).
2432 Ž An attempt to pop an operand from an empty register (stack underflow).
2434 Ž An operand is a NaN.
2436 Ž The operands cause the operation to be indeterminate (square root of a
2437 negative number, 0/0).
2439 An invalid operation generally indicates a program error.
2443 If an instruction attempts to divide a finite nonzero operand by zero, the
2444 80287 will report a zero divide exception.
2447 Denormalized Operand
2448 If an instruction attempts to operate on a denormal, the NPX reports the
2449 denormalized operand exception. This exception allows users to implement in
2450 software an option of the proposed IEEE standard specifying that operands
2451 must be prenormalized before they are used.
2454 Numeric Overflow and Underflow
2455 If the exponent of a numeric result is too large for the destination real
2456 format, the 80287 signals a numeric overflow. Conversely, if the exponent of
2457 a result is too small to be represented in the destination format, a numeric
2458 underflow is signaled. If either of these exceptions occur, the result of
2459 the operation is outside the range of the destination real format.
2461 Typical algorithms are most likely to produce extremely large and small
2462 numbers in the calculation of intermediate, rather than final, results.
2463 Because of the great range of the temporary real format (recommended as the
2464 destination format for intermediates), overflow and underflow are
2465 relatively rare events in most 80287 applications.
2469 If the result of an operation is not exactly representable in the
2470 destination format, the 80287 rounds the number and reports the precision
2471 exception. For example, the fraction 1/3 cannot be precisely represented in
2472 binary form. This exception occurs frequently and indicates that some
2473 (generally acceptable) accuracy has been lost; it is provided for
2474 applications that need to perform exact arithmetic only.
2477 Handling Numeric Errors
2478 When numeric errors occur, the NPX takes one of two possible courses of
2481 Ž The NPX can itself handle the error, producing the most reasonable
2482 result and allowing numeric program execution to continue undisturbed.
2484 Ž A software exception handler can be invoked by the CPU to handle the
2487 Each of the six exception conditions described above has a corresponding
2488 flag bit in the 80287 status word and a mask bit in the 80287 control word.
2489 If an exception is masked (the corresponding mask bit in the control
2490 word = 1), the 80287 takes an appropriate default action and continues with
2491 the computation. If the exception is unmasked (mask = 0), the 80287 asserts
2492 the ERROR output to the 80286 to signal the exception and invoke a
2493 software exception handler.
2495 The NPX reports an exception by setting the corresponding flag in the NPX
2496 status word to 1. The NPX then checks the corresponding exception mask in
2497 the control word to determine if it should "field" the exception (mask = 1),
2498 or if it should signal the exception to the CPU to invoke a software
2499 exception handler (mask = 0).
2501 If the mask is set, the exception is said to be masked (from user
2502 software), and the NPX executes its on-chip masked response for that
2503 exception. If the mask is not set (mask = 0), the exception is unmasked,
2504 and the NPX performs its unmasked response. The masked response always
2505 produces a standard result, then proceeds with the instruction. The unmasked
2506 response always traps to a software exception handler, allowing the CPU to
2507 recognize and take action on the exception. Table 1-17 gives a complete
2508 description of all exception conditions and the NPX's masked response.
2510 Note that when exceptions are masked, the NPX may detect multiple
2511 exceptions in a single instruction, because it continues executing the
2512 instruction after performing its masked response. For example, the 80287
2513 could detect a denormalized operand, perform its masked response to this
2514 exception, and then detect an underflow.
2517 Table 1-17. Exception Conditions and Masked Responses
2520 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2521 Condition Masked Response
2522 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2524 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2525 Source register is tagged empty Return real indefinite.
2526 (usually due to stack underflow).
2528 Destination register is not tagged Return real indefinite
2529 empty (usually due to stack (overwrite destination value).
2532 One or both operands is a NaN. Return NaN with larger absolute
2533 value (ignore signs).
2535 (Compare and test operations only): Set condition codes "not
2536 one or both operands is a NaN. comparable."
2538 (Addition operations only): closure Return real indefinite.
2539 is affine and operands are
2540 opposite-signed infinities; or
2541 closure is projective and both
2542 operands are ý (signs immaterial).
2544 (Subtraction operations only): Return real indefinite.
2545 closure is affine and operands are
2546 like-signed infinities; or closure
2547 is projective and both operands are
2548 ý (signs immaterial).
2550 (Multiplication operations only): Return real indefinite.
2553 (Division operations only): Return real indefinite.
2554 ý ÷ ý; or 0 ÷ 0; or 0 ÷ pseudo
2555 zero; or divisor is denormal
2558 (FPREM instruction only): modulus Return real indefinite, set
2559 (divisor) is unnormal or denormal; condition code = "complete
2560 or dividend is ý. remainder."
2562 (FSQRT instruction only): operand Return real indefinite.
2563 is nonzero and negative; or operand
2564 is denormal or unnormal; or closure
2565 is affine and operand is -ý; or
2566 closure is projective and operand
2569 (Compare operations only): closure Set condition code = "not
2570 is projective and ý is being comparable."
2571 compared with 0, a normal or ý.
2573 (FTST instruction only): closure is Set condition code = "not
2574 projective and operand is ý. comparable."
2576 (FIST, FISTP instructions only): Store integer indefinite.
2577 source register is empty, a NaN,
2578 denormal, unnormal, ý, or exceeds
2579 representable range of destination.
2581 (FBSTP instruction only): source Stored packed decimal
2582 register is empty, a NaN, denormal, indefinite.
2583 unnormal, ý, or exceeds 18 decimal
2586 (FST, FSTP instructions only): Store real indefinite.
2587 destination is short or long real
2588 and source register is an unnormal
2589 with exponent in range.
2591 (FXCH instruction only): one or Change empty register(s) to
2592 both registers is tagged empty. real indefinite and then
2597 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2598 Condition Masked Response
2599 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2600 Denormalized Operand
2601 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2602 (FLD instruction only): source No special action; load as usual.
2603 operand is denormal.
2605 (Arithmetic operations only): one Convert (in a work area) the
2606 or both operands is denormal. operand to the equivalent unnormal
2609 (Compare and test operations only): Convert (in a work area) any
2610 one or both operands is denormal denormal to the equivalent
2611 or unnormal other than pseudo unnormal; normalize as much as
2612 zero). possible, and proceed with
2614 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2616 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2617 (Division operations only): Return ý signed with "exclusive or"
2618 divisor = 0. of operand signs.
2619 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2621 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2622 (Arithmetic operations only): Return properly signed ý and signal
2623 rounding is nearest or chop, and precision exception.
2624 exponent of true result > 16,383.
2626 (FST, FSTP instructions only): Return properly signed ý and signal
2627 rounding is nearest or chop, and precision exception.
2628 exponent of true result > +127
2629 (short real destination) or > +1023
2630 (long real destination).
2631 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2633 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2634 (Arithmetic operations only): Denormalize until exponent rises to
2635 exponent of true result < -16,382 -16,382 (true), round significand
2636 (true). to 64 bits. If denormalized rounded
2637 significand = 0, then return true
2638 0; else, return denormal (tag =
2639 special, biased exponent = 0).
2641 (FST, FSTP instructions only): Denormalize until exponent rises to
2642 destination is short real and -126 (true), round significand to
2643 exponent of true result < -126 24 bits, store true 0 if
2644 (true). denormalized rounded significand = 0;
2645 else, store denormal (biased
2648 (FST, FSTP instructions only): Denormalize until exponent rises to
2649 destination is long real and -1022 (true), round significand to
2650 exponent of true result < -1022 53 bits, store true 0 if rounded
2651 (true). denormalized significand = 0; else,
2652 store denormal (biased exponent = 0).
2653 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2655 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2656 True rounding error occurs. No special action.
2658 Masked response to overflow No special action.
2659 exception earlier in instruction.
2662 Automatic Exception Handling
2663 As described in the previous section, when the 80287 NPX encounters an
2664 exception condition whose corresponding mask bit in the NPX control word is
2665 set, the NPX automatically performs an internal fix-up (masked-exception)
2666 response. The 80287 NPX has a default fix-up activity for every possible
2667 exception condition it may encounter. These masked-exception responses are
2668 designed to be safe and are generally acceptable for most numeric
2671 As an example of how even severe exceptions can be handled safely and
2672 automatically using the NPX's default exception responses, consider a
2673 calculation of the parallel resistance of several values using only the
2674 standard formula (figure 1-11). If R{1} becomes zero, the circuit
2675 resistance becomes zero. With the divide-by-zero and precision exceptions
2676 masked, the 80287 NPX will produce the correct result.
2678 By masking or unmasking specific numeric exceptions in the NPX control
2679 word, NPX programmers can delegate responsibility for most exceptions to the
2680 NPX, reserving the most severe exceptions for programmed exception handlers.
2681 Exception-handling software is often difficult to write, and the NPX's
2682 masked responses have been tailored to deliver the most reasonable result
2683 for each condition. For the majority of applications, programmers will find
2684 that masking all exceptions other than Invalid Operation will yield
2685 satisfactory results with the least programming effort. An Invalid
2686 Operation exception normally indicates a fatal error in a program that must
2687 be corrected; this exception should not normally be masked.
2689 The exception flags in the NPX status word provide a cumulative record of
2690 exceptions that have occurred since these flags were last cleared. Once set,
2691 these flags can be cleared only by executing the FCLEX (clear exceptions)
2692 instruction, by reinitializing the NPX, or by overwriting the flags with an
2693 FRSTOR or FLDENV instruction. This allows a programmer to mask all
2694 exceptions (except invalid operation), run a calculation, and then inspect
2695 the status word to see if any exceptions were detected at any point in the
2699 Figure 1-11. Arithmetic Example Using Infinity
2704 �‘‘‘‘‘‘‘‘‘/\/\/\/‘‘‘‘‘‘‘‘‘‘� 1
2705 � � EQUIVALENT = ‘‘‘‘‘‘‘‘‘‘‘‘
2706 � � RESISTANCE 1 1 1
2707 � R{2} � ‘‘ + ‘‘ + ‘‘
2708 �‘‘‘‘‘‘‘‘‘/\/\/\/‘‘‘‘‘‘‘‘‘‘� R{1} R{2} R{3}
2712 ”‘‘‘‘‘‘‘‘‘/\/\/\/‘‘‘‘‘‘‘‘‘‘•
2715 Software Exception Handling
2716 If the NPX encounters an unmasked exception condition, it signals the
2717 exception to the 80286 CPU using the ERROR status line between the two
2720 The next time the 80286 CPU encounters a WAIT or ESC instruction in its
2721 instruction stream, the 80286 will detect the active condition of the
2722 ERROR status line and automatically trap to an exception response
2723 routine using interrupt #16‘‘the Processor Extension Error exception.
2725 This exception response routine is typically a part of the systems
2726 software. Typical exception responses may include:
2728 Ž Incrementing an exception counter for later display or printing
2730 Ž Printing or displaying diagnostic information (e.g., the 80287
2731 environment and registers)
2733 Ž Aborting further execution
2735 Ž Using the exception pointers to build an instruction that will run
2736 without exception andexecuting it
2738 Application programmers on 80286 systems having systems software support
2739 for the 80287 NPX should consult their references for the appropriate system
2740 response to NPX exceptions. For systems programmers, specific details on
2741 writing software exception handlers are included in the section
2742 "System-Level Numeric Programming" later in this manual.
2744 The 80287 NPX differs from the 8087 NPX in the manner in which numeric
2745 exceptions are signalled to the CPU; the 8087 requires an interrupt
2746 controller (8259A) to interrupt the CPU, while the 80287 does not.
2747 Programmers upgrading 8087 software to operate on an 80287 should be aware
2748 of these differences and any implications they might have on numeric
2749 exception-handling software. Appendix B explains the differences between
2750 the 80287 and the 8087 NPX in greater detail.
2753 Chapter 2 Programming Numeric Applications
2755 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2757 Programmers developing applications for the 80287 have a wide range of
2758 instructions and programming alternatives from which to choose.
2760 The following sections describe the 80287 instruction set in detail, and
2761 follow up with a discussion of several of the programming facilities that
2762 are available to programmers of 80287.
2765 The 80287 NPX Instruction Set
2766 This section describes the operation of all 80287 instructions. Within this
2767 section, the instructions are divided into six functional classes:
2769 Ž Data Transfer instructions
2770 Ž Arithmetic instructions
2771 Ž Comparison instructions
2772 Ž Transcendental instructions
2773 Ž Constant instructions
2774 Ž Processor Control instructions
2776 At the end of this section, each of the instructions is described in terms
2777 of its execution speed, bus transfers, and exceptions, as well as a coding
2778 example for each combination of operands accepted by the instruction. For
2779 easy reference, this information is concentrated into a table, organized
2780 alphabetically by instruction mnemonic.
2782 Throughout this section, the instruction set is described as it appears to
2783 the ASM286 programmer who is coding a program. Appendix A covers the actual
2784 machine instruction encodings, which are principally of use to those reading
2785 unformatted memory dumps, monitoring instruction fetches on the bus, or
2786 writing exception handlers.
2789 Compatibility with the 8087 NPX
2790 The instruction set for the 80287 NPX is largely the same as that for the
2791 8087 NPX used with 8086 and 8088 systems. Most object programs generated for
2792 the 8087 will execute without change on the 80287. Several instructions are
2793 new to the 80287, and several 8087 instructions perform no useful function
2794 on the 80287. Appendix B at the back of this manual gives details of these
2795 instruction set differences and of the differences in the ASM86 and ASM286
2800 The typical NPX instruction accepts one or two operands as inputs, operates
2801 on these, and produces a result as an output. Operands are most often (the
2802 contents of) register or memory locations. The operands of some instructions
2803 are predefined; for example, FSQRT always takes the square root of the
2804 number in the top stack element. Others allow, or require, the programmer to
2805 explicitly code the operand(s) along with the instruction mnemonic. Still
2806 others accept one explicit operand and one implicit operand, which is
2807 usually the top stack element.
2809 Whether supplied by the programmer or utilized automatically, the two basic
2810 types of operands are sources and destinations. A source operand simply
2811 supplies one of the inputs to an instruction; it is not altered by the
2812 instruction. Even when an instruction converts the source operand from one
2813 format to another (e.g., real to integer), the conversion is actually
2814 performed in an internal work area to avoid altering the source operand. A
2815 destination operand may also provide an input to an instruction. It is
2816 distinguished from a source operand, however, because its content may be
2817 altered when it receives the result produced by the operation; that is, the
2818 destination is replaced by the result.
2820 Many instructions allow their operands to be coded in more than one way.
2821 For example, FADD (add real) may be written without operands, with only a
2822 source or with a destination and a source. The instruction descriptions in
2823 this section employ the simple convention of separating alternative operand
2824 forms with slashes; the slashes, however, are not coded. Consecutive
2825 slashes indicate an option of no explicit operands. The operands for FADD
2826 are thus described as
2828 //source/destination, source
2830 This means that FADD may be written in any of three ways:
2834 FADD destination, source
2836 When reading this section, it is important to bear in mind that memory
2837 operands may be coded with any of the CPU's memory addressing modes. To
2838 review these modes‘‘direct, register indirect, based, indexed, based
2839 indexed‘‘refer to the 80286 Programmer's Reference Manual. Table 2-17 later
2840 in this chapter also provides several addressing mode examples.
2843 Data Transfer Instructions
2844 These instructions (summarized in table 2-1) move operands among elements
2845 of the register stack, and between the stack top and memory. Any of the
2846 seven data types can be converted to temporary real and loaded (pushed) onto
2847 the stack in a single operation; they can be stored to memory in the same
2848 manner. The data transfer instructions automatically update the 80287 tag
2849 word to reflect the register contents following the instruction.
2853 FLD (load real) loads (pushes) the source operand onto the top of the
2854 register stack. This is done by decrementing the stack pointer by one and
2855 then copying the content of the source to the new stack top. The source may
2856 be a register on the stack (ST(i)) or any of the real data types in memory.
2857 Short and long real source operands are converted to temporary real
2858 automatically. Coding FLD ST(0) duplicates the stack top.
2862 FST (store real) transfers the stack top to the destination, which may be
2863 another register on the stack or a short or long real memory operand. If the
2864 destination is short or long real, the significand is rounded to the width
2865 of the destination according to the RC field of the control word, and the
2866 exponent is converted to the width and bias of the destination format.
2868 If, however, the stack top is tagged special (it contains ý, a NaN, or a
2869 denormal) then the stack top's significand is not rounded but is chopped (on
2870 the right) to fit the destination. Neither is the exponent converted, but it
2871 also is chopped on the right and transferred "as is." This preserves the
2872 value's identification as ý or a NaN (exponent all ones) or a denormal
2873 (exponent all zeros) so that it can be properly loaded and tagged later in
2874 the program if desired.
2877 Table 2-1. Data Transfer Instructions
2878 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
2880 –‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2882 � FST � Store real �
2883 � FSTP � Store real and pop �
2884 � FXCH � Exchange registers �
2885 –‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2886 � Integer Transfers �
2887 –‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2888 � FILD � Integer load �
2889 � FIST � Integer store �
2890 � FISTP � Integer store and pop �
2891 –‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2892 � Packed Decimal Transfers �
2893 –‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2894 � FBLD � Packed decimal (BCD) load �
2895 � FBSTP � Packed decimal (BCD) store and pop �
2896 ”‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
2900 FSTP (store real and pop) operates identically to FST except that the stack
2901 is popped following the transfer. This is done by tagging the top stack
2902 element empty and then incrementing ST. FSTP permits storing to a temporary
2903 real memory variable, whereas FST does not. Coding FSTP ST(0) is equivalent
2904 to popping the stack with no data transfer.
2908 FXCH (exchange registers) swaps the contents of the destination and the
2909 stack top registers. If the destination is not coded explicitly, ST(1) is
2910 used. Many 80287 instructions operate only on the stack top; FXCH provides a
2911 simple means of effectively using these instructions on lower stack
2912 elements. For example, the following sequence takes the square root of the
2913 third register from the top:
2921 FILD (integer load) converts the source memory operand from its binary
2922 integer format (word, short, or long) to temporary real and loads (pushes)
2923 the result onto the stack. The (new) stack top is tagged zero if all bits in
2924 the source were zero, and is tagged valid otherwise.
2928 FIST (integer store) rounds the content of the stack top to an integer
2929 according to the RC field of the control word and transfers the result to
2930 the destination. The destination may define a word or short integer
2931 variable. Negative zero is stored in the same encoding as positive zero:
2936 FISTP (integer and pop) operates like FIST and also pops the stack
2937 following the transfer. The destination may be any of the binary integer
2942 FBLD (packed decimal (BCD) load) converts the content of the source operand
2943 from packed decimal to temporary real and loads (pushes) the result onto the
2944 stack. The sign of the source is preserved, including the case where the
2945 value is negative zero. FBLD is an exact operation; the source is loaded
2946 with no rounding error.
2948 The packed decimal digits of the source are assumed to be in the range
2949 0-9H. The instruction does not check for invalid digits (A-FH) and the
2950 result of attempting to load an invalid encoding is undefined.
2954 FBSTP (packed decimal (BCD) store and pop) converts the content of the
2955 stack top to a packed decimal integer, stores the result at the destination
2956 in memory, and pops the stack. FBSTP produces a rounded integer from a
2957 nonintegral value by adding 0.5 to the value and then chopping. Users who
2958 are concerned about rounding may precede FBSTP with FRNDINT.
2961 Arithmetic Instructions
2962 The 80287's arithmetic instruction set (table 2-2) provides a wealth of
2963 variations on the basic add, subtract, multiply, and divide operations, and
2964 a number of other useful functions. These range from a simple absolute value
2965 to a square root instruction that executes faster than ordinary division;
2966 80287 programmers no longer need to spend valuable time eliminating square
2967 roots from algorithms because they run too slowly. Other arithmetic
2968 instructions perform exact modulo division, round real numbers to integers,
2969 and scale values by powers of two.
2971 The 80287's basic arithmetic instructions (addition, subtraction,
2972 multiplication, and division) are designed to encourage the development of
2973 very efficient algorithms. In particular, they allow the programmer to
2974 minimize memory references and to make optimum use of the NPX register
2977 Table 2-3 summarizes the available operation/operand forms that are
2978 provided for basic arithmetic. In addition to the four normal operations,
2979 two "reversed" instructions make subtraction and division "symmetrical" like
2980 addition and multiplication. The variety of instruction and operand forms
2981 give the programmer unusual flexibility:
2983 Ž Operands may be located in registers or memory.
2985 Ž Results may be deposited in a choice of registers.
2987 Ž Operands may be a variety of NPX data types: temporary real, long
2988 real, short real, short integer or word integer, with automatic
2989 conversion to temporary real performed by the 80287.
2991 Five basic instruction forms may be used across all six operations, as
2992 shown in table 2-3. The classicial stack form may be used to make the 80287
2993 operate like a classical stack machine. No operands are coded in this form,
2994 only the instruction mnemonic. The NPX picks the source operand from the
2995 stack top and the destination from the next stack element. It then pops the
2996 stack, performs the operation, and returns the result to the new stack top,
2997 effectively replacing the operands by the result.
2999 The register form is a generalization of the classical stack form; the
3000 programmer specifies the stack top as one operand and any register on the
3001 stack as the other operand. Coding the stack top as the destination provides
3002 a convenient way to access a constant, held elsewhere in the stack, from
3003 the stack top. The converse coding (ST is the source operand) allows, for
3004 example, adding the top into a register used as an accumulator.
3006 Often the operand in the stack top is needed for one operation but then is
3007 of no further use in the computation. The register pop form can be used to
3008 pick up the stack top as the sourced operand, and then discard it by
3009 popping the stack. Coding operands of ST(1), ST with a register pop
3010 mnemonic is equivalent to a classical stack operation: the top is popped
3011 and the result is left at the new top.
3013 The two memory forms increase the flexibity of the 80287's arithmetic
3014 instructions. They permit a real number or a binary integer in memory to
3015 be used directly as a source operand. This is a very useful facility in
3016 situations where operands are not used frequently enough to justify
3017 holding them in registers. Note that any memory addressing mode may be
3018 used to define these operands, so they may be elements in arrays,
3019 structures, or other data organizations, as well as simple scalars.
3021 The six basic operations are discussed further in the paragraphs following
3022 table 2-3, and descriptions of the remaining seven arithmetic operations
3025 Table 2-2. Arithmetic Instructions
3029 FADDP Add real and pop
3034 FSUBP Subtract real and pop
3035 FISUB Integer subtract
3036 FSUBR Subtract real reversed
3037 FSUBRP Subtract real reversed and pop
3038 FISUBR Integer subtract reversed
3042 FMULP Multiply real and pop
3043 FIMUL Integer multiply
3047 FDIVP Divide real and pop
3048 FIDIV Integer divide
3049 FDIVR Divide real reversed
3050 FDIVRP Divide real reversed and pop
3051 FIDIVR Integer divide reversed
3056 FPREM Partial remainder
3057 FRNDINT Round to integer
3058 FXTRACT Extract exponent and significand
3063 Table 2-3. Basic Arithmetic Instruction and Operands
3065 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
3066 � Instruction � Mnemonic� Operand Forms � ASM286 Example�
3067 � Form � Form � destination, source � �
3068 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
3069 �Classical stack� Fop � {ST(1),ST} � FADD �
3070 �Register � Fop � ST(i),ST or ST,ST(i) � FSUB ST,ST(3)�
3071 �Register pop � FopP � ST(i),ST � FMULP ST(2),ST�
3072 �Real memory � Fop � {ST,} short-real/long-real � FDIV AZIMUTH �
3073 �Integer memory � Flop � {ST,} word-integer/ � FIDV N_PULSES �
3074 � � � short-integer � �
3075 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
3077 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3080 Braces({ }) surround inplicit operands; these are not coded, and
3081 are shown here for information only.
3083 op = ADD destinaiton
\e destination + source
3084 SUB destination
\e destination - source
3085 SUBR destination
\e soure - destination
3086 MUL destination
\e destination ¨ source
3087 DIV destination
\e destination ÷ source
3088 DIVR destination
\e source ÷ destination
3089 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3093 FADD //source/destination,source
3094 FADDP //destination/source
3097 The addition instructions (add real, add real and pop, integer add) add
3098 the source and destination operands and return the sum to the destination.
3099 The operand at the stack top may be doubled by coding:
3105 FSUB //source/destinaton,source
3106 FSUBP //destination/source
3109 The normal subtraction instruction (subtract real,subtract real and pop,
3110 integer subtract) subtract the source operand from the destination and
3111 return the difference to the destination.
3114 REVERSED SUBTRACTION
3115 FSUBR //source/destinaton,source
3116 FSUBRP //destination/source
3119 The reversed subtraction instructions (subtract real reversed, subtract
3120 real reversed and pop, integer subtract reversed) subtract the destination
3121 from the source and return the difference to the destination.
3125 FMUL //source/destination,source
3126 FMULP destination,source
3129 The multiplication instructions (multiply real, multiply real and pop,
3130 integer multiply) multiply the source and destination operands and return
3131 the product to the destination. Coding FMUL ST,ST(0) squares the content
3136 FDIV //source/destination,source
3137 FDIVP destination,source
3140 The normal division instructions (divide real, divide real and pop,
3141 integer divide) divide the destination by the source and return the
3142 quotient to the destination.
3146 FDIVR //source destination, source
3147 FDIVRP destination,source
3150 The reversed division instructions (divide real reversed, divide real
3151 reversed and pop, integer divide reversed) divide the source operand by
3152 the destination and return the quotient to the destination.
3156 FSQRT (square root) replaces the content of the top stack element with its
3157 square root. (Note: The square root of -0 is defined to be -0.)
3161 FSCALE (scale) interprets the value contained in ST(1) as an integer and
3162 adds this value to the exponent of the number in ST. This is equivalent to
3164 ST
\e ST * 2^(ST(1))
3166 Thus FSCALE provides rapid multiplication or division by integal powers of
3167 2. It is particularly useful for scaling the elements of a vector.
3169 Note that FSCALE assumes the scale factor in ST(1) is an integral value in
3170 the range -2^(15) ¾ x < 2^(15). If the value is not integral, but is
3171 in-range and is greater in magnitude than 1, FSCALE uses the nearest integer
3172 smaller in magnitude; i.e., it chops the value toward 0. If the value is out
3173 of range, or 0 < �x� < 1, the instruction will produce an undefined result
3174 and will not signal an exception. The recommended practice is to load the
3175 scale factor from a word integer to ensure correct operation.
3179 FPREM (partial remainder) performs modulo division of the top stack
3180 element by the next stack element, i.e., ST(1) is the modulus. FPREM
3181 produces an exact result; the precision exception does not occur. The sign
3182 of the remainder is the same as the sign of the orginal dividend.
3184 FPREM operates by performing successive scaled subtractions; obtaining the
3185 exact remainder when the operands differ greatly in magnitude can consume
3186 large amounts of execution time. Because the 80287 cas only be preempted
3187 between instructions, the remainder function could seriously increase
3188 interrupt latency in these cases. Accordingly, the instruction is designed
3189 to be executed interactively in a software-controlled loop.
3191 FPREM can reduce a magnitude difference of up to 264 in one execution. If
3192 FPREM produces a remainder that is less than the modulus, the function is
3193 complete and bit C2 of the status word condition code is cleared. If the
3194 function is incomplete, C2 is set to 1; the result is ST is then called
3195 the partial remainder. Software can inspect C2 by storing the status word
3196 following execution of FPREM and re-execute the instruction (using the
3197 partial remainder in ST as the dividend), until C2 is cleared.
3198 Alternatively, a program can determine when the function is complete by
3199 comparing ST to ST(1). If ST > ST(1), then FPREM must be executed again; if
3200 ST = ST(1), then the remainder is 0; if ST < ST(1), then the remainder is
3201 ST. A higher priority interrupting routine that needs the 80287 can force a
3202 context switch between the instructions in the remainder loop.
3204 An important use for FPREM is to reduce arguments (operands) of periodic
3205 transcendental functions to the range permitted by these instructions. For
3206 example, the FPTAN (tangent) instruction requires its argument to be less
3207 than Ò/4. Using Ò/4 as a modulus, FPTAN will reduce an argument so that it
3208 is in range of FPTAN. Because FPREM produces an exact result, the argument
3209 reduction does not introduce roundoff error into the calculation, even if
3210 several iterations are required to bring the argument into range. (The
3211 rounding of Ò does not create the effect of a rounded argument, but of a
3214 FPREM also provides the least-significant three bits of the quotient
3215 generated by FPREM (in C{3}, C{1}, C{0}). This is also important for
3216 trancendental argument reduction, because it locates the original angle in
3217 the correct one of eight Ò/4 segments of the unit circle (see table 2-4).
3218 If the quotient is less than 4, then C0 will be the value of C3 before
3219 FPREM was executed. If the quotient is less than 2, then C3 will be the
3220 value of C1 before FPREM was executed.
3224 FRNDINT (round to integer) rounds the top stack element to an integer. For
3225 example, assume that ST contains the 80287 real number encoding of the
3226 decimal value 155.625. FRNDINT will change the value to 155 if the RC field
3227 of the control word is set to down or chop, or to 156 if it is set to up or
3232 FXTRACT (extract exponent and significand) "decomposes" the number in the
3233 stack top into two numbers that represent the actual value of the operand's
3234 exponent and significand fields. The "exponent" replaces the original
3235 operand on the stack and the "significand" is pushed onto the stack.
3236 Following execution of FXTRACT, ST (the new stack top) contains the value of
3237 the original significand expressed as a real number: its sign is the same as
3238 the operand's, its exponent is 0 true (16,383 or 3FFFH biased), and its
3239 significand is identical to the original operand's. ST(1) contains the
3240 value of the original operand's true (unbiased) exponent expressed as a real
3241 number. If the original operand is zero, FXTRACT produces zeros in ST and
3242 ST(1) and both are signed as the original operand.
3244 To clarify the operation of FXTRACT, assume ST contains a number of whose
3245 true exponent is +4 (i.e., its exponent field contains 4003H). After
3246 executing FXTRACT, ST(1) will contain the real number +4.0; its sign will be
3247 positive, its exponent field will contain 4001H (+2 true) and its
3248 significand field will contain 1{
\x1e}00...00B. In other words, the value in
3249 ST(1) will be 1.0 * 2^(2) = 4. If ST contains an operand whose true exponent
3250 is -7 (i.e., its exponent field contains 3FF8H), then FXTRACT will return an
3251 "exponent" of -7.0; after the instruction executes, ST(1)'s sign and
3252 exponent fields will contain C001H (negative sign, true exponent of 2), and
3253 its significand will be 1{
\x1e}1100...00B. In other words, the value in ST(1)
3254 will be -1.11 * 2^(2) = -7.0. In both cases, following FXTRACT, ST's sign
3255 and significand fields will be the same as the original operand's, and its
3256 exponent field will contain 3FFFH (0 true).
3258 FXTRACT is useful in conjunction with FBSTP for converting numbers in 80287
3259 temporary real format to decimal representations (e.g., for printing or
3260 displaying). It can also be useful for debugging, because it allows the
3261 exponent and significant parts of a real number to be examined separately.
3265 FABS (absolute value) changes the top stack element to its absolute value
3266 by making its sign positive.
3270 FCHS (change sign) complements (reverses) the sign of the top stack
3274 Table 2-4. Condition Code Interpretation after FPREM
3276 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
3277 � ’‘‘Condition Code‘‘“ �
3278 � C3 C2 C1 C0 Interpretation after FPREM �
3279 –‘‘‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
3280 � X � 1 � X � X � Incomplete Reduction; �
3281 � � � � � further iteration is required for �
3282 � � � � � complete reduction. �
3283 � � � � � Complete Reduction; �
3284 � � � � � C1, C3, and C0 contain the three least- �
3285 � � � � � significant bits of quotient: �
3286 � 0 � 0 � 0 � 0 � (Quotient) MOD 8 = 0 �
3287 � 0 � 0 � 0 � 1 � (Quotient) MOD 8 = 4 �
3288 � 0 � 0 � 1 � 0 � (Quotient) MOD 8 = 1 �
3289 � 0 � 0 � 1 � 1 � (Quotient) MOD 8 = 5 �
3290 � 1 � 0 � 0 � 0 � (Quotient) MOD 8 = 2 �
3291 � 1 � 0 � 0 � 1 � (Quotient) MOD 8 = 6 �
3292 � 1 � 0 � 1 � 0 � (Quotient) MOD 8 = 3 �
3293 � 1 � 0 � 1 � 1 � (Quotient) MOD 8 = 7 �
3294 ”‘‘‘‘‘™‘‘‘‘‘™‘‘‘‘‘™‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
3297 Comparison Instructions
3298 Each of these instructions (table 2-5) analyzes the top stack element,
3299 often in relationship to another operand, and reports the result in the
3300 status word condition code. The basic operations are compare, test (compare
3301 with zero), and examine (report tag, sign, and normalization). Special
3302 forms of the compare operation are provided to optimize algorithms by
3303 allowing direct comparisons with binary integers and real numbers in memory,
3304 as well as popping the stack after a comparison.
3306 The FSTSW (store status word) instruction may be used following a
3307 comparison to transfer the condition code to memory for inspection.
3309 Note that instructions other than those in the comparison group may update
3310 the condition code. To ensure that the status word is not altered
3311 inadvertently, store it immediately following a comparison operation.
3315 FCOM (compare real) compares the stack top to the source operand. The
3316 source operand may be a register on the stack, or a short or long real
3317 memory operand. If an operand is not coded, ST is compared to ST(1).
3318 Positive and negative forms of zero compare identically as if they were
3319 unsigned. Following the instruction, the condition codes reflect the order
3320 of the operands as shown in table 2-6.
3322 NaNs and ý (projective) cannot be compared and return C3 = C0 = 1 as shown
3327 FCOMP (compare real and pop) operates like FCOM, and in addition pops the
3332 FCOMPP (compare real and pop twice) operates like FCOM and additionally
3333 pops the stack twice, discarding both operands. The comparison is of the
3334 stack top to ST(1); no operands may be explicitly coded.
3338 FICOM (integer compare) converts the source operand, which may reference a
3339 word or short binary integer variable, to temporary real and compares the
3344 FICOMP (integer compare and pop) operates identically to FICOM and
3345 additionally discards the value in ST by popping the stack.
3349 FTST (test) tests the top stack element by comparing it to zero. The result
3350 is posted to the condition codes as shown in table 2-7.
3354 FXAM (examine) reports the content of the top stack element as
3355 positive/negative and NaN/unnormal/denormal/normal/zero, or empty.
3356 Table 2-8 lists and interprets all the condition code values that FXAM
3357 generates. Although four different encodings may be returned for an empty
3358 register, bits C3 and C0 of the condition code are both 1 in all encodings.
3359 Bits C2 and C1 should be ignored when examining for empty.
3362 Table 2-5. Comparison Instructions
3365 FCOMP Compare real and pop
3366 FCOMPP Compare real and pop twice
3367 FICOM Integer compare
3368 FICOMP Integer compare and pop
3373 Table 2-6. Condition Code Interpretation after FCOM
3375 ’‘‘ Condition Code ‘‘“
3376 C3 C2 C1 C0 Interpretation after FCOM
3381 1 1 X 1 ST is not comparable
3384 Table 2-7. Condition Code Interpretation after FTST
3386 ’‘‘ Condition Code ‘‘“
3387 C3 C2 C1 C0 Interpretation after FTST
3392 1 1 X 1 ST is not comparable; (i.e., it
3393 is a NaN or projective infinity)
3396 Table 2-8. FXAM Condition Code Settings
3398 ’‘‘‘ Condition Code ‘‘‘“
3399 C3 C2 C1 C0 Interpretation
3419 Transcendental Instructions
3420 The instructions in this group (table 2-9) perform the time-consuming core
3421 calculations for all common trigonometric, inverse trigonometric,
3422 hyperbolic, inverse hyperbolic, logarithmic, and exponential functions.
3423 Prologue and epilogue software may be used to reduce arguments to the range
3424 accepted by the instructions and to adjust the result to correspond to the
3425 original arguments if necessary. The transcendentals operate on the top one
3426 or two stack elements, and they return their results to the stack, also.
3428 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3430 The transcendental instructions assume that their operands are valid and
3431 in-range. The instruction descriptions in this section provide the
3432 allowed operand range of each instruction.
3433 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3435 All operands to a transcendental must be normalized; denormals, unnormals,
3436 infinities, and NaNs are considered invalid. (Zero operands are accepted by
3437 some functions and are considered out-of-range by others). If a
3438 transcendental operand is invalid or out-of-range, the instruction will
3439 produce an undefined result without signalling an exception. It is the
3440 programmer's responsibility to ensure that operands are valid and in-range
3441 before executing a transcendental. For periodic functions, FPREM may be
3442 used to bring a valid operand into range.
3448 FPTAN (partial tangent) computes the function Y/X = TAN(Ú). Ú is taken
3449 from the top stack element; it must lie in the range 0 ¾ Ú ¾ Ò/4. The result
3450 of the operation is a ratio; Y replaces Ú in the stack and X is pushed,
3451 becoming the new stack top.
3453 The ratio result of FPTAN and the ratio argument of FPATAN are designed to
3454 optimize the calculation of the other trigonometric functions, including
3455 SIN, COS, ARCSIN, and ARCCOS. These can be derived from TAN and ARCTAN via
3456 standard trigonometric identities.
3460 0 ¾ ST(1) < ST(0) < ý
3462 FPATAN (partial arctangent) computes the function Ú = ARCTAN(Y/X). X is
3463 taken from the top stack element and Y from ST(1). Y and X must observe the
3464 inequality 0 ¾ Y < X < ý. The instruction pops the stack and returns Ú to
3465 the (new) stack top, overwriting the Y operand.
3471 F2XM1 (2 to the X minus 1) calculates the function Y = 2^(X) - 1. X is taken
3472 from the stack top and must be in the range 0 ¾ X ¾ 0.5. The result Y
3473 replaces X at the stack top.
3475 This instruction is designed to produce a very accurate result even when X
3476 is close to 0. To obtain Y = 2^(X), add 1 to the result delivered by F2XM1.
3478 The following formulas show how values other than 2 may be raised to a
3481 10^(x) = 2^(x * LOG{2}10)
3482 e^(x) = 2^(x * LOG{2}e)
3483 y^(x) = 2^(x * LOG{2}Y)
3485 As shown in the next section, the 80287 has built-in instructions for
3486 loading the constants LOG{2}10 and LOG{2}e, and the FYL2X instruction may be
3487 used to calculate X * LOG{2}Y.
3491 0 < ST(0) < ý - ý < ST(1) < ý
3493 FYL2X (Y log base 2 of X) calculates the function Z = Y * LOG{2}X. X is
3494 taken from the stack top and Y from ST(1). The operands must be in the
3495 ranges 0 < X < ý and -ý < Y < +ý. The instruction pops the stack and returns
3496 Z at the (new) stack top, replacing the Y operand.
3498 This function optimizes the calculations of log to any base other than two,
3499 because a multiplication is always required:
3505 0 ¾ �ST(0)� < (1 - (¹2/2))
3508 FYL2XP1 (Y log base 2 of (X + 1)) calculates the function
3509 Z = Y * LOG{2}(X+1). X is taken from the stack top and must be in the range
3510 0 ¾ �X� < (1 - (¹2/2)). Y is taken from ST(1) and must be in the range
3511 -ý < Y < ý. FYL2XP1 pops the stack and returns Z at the (new) stack top,
3514 The instruction provides improved accuracy over FYL2X when computing the
3515 log of a number very close to 1, for example 1 + ¯ where ¯ << 1. Providing ¯
3516 rather than 1 + ¯ as the input to the function allows more significant
3517 digits to be retained.
3520 Table 2-9. Transcendental Instructions
3522 FPTAN Partial tangent
3523 FPATAN Partial arctangent
3526 FYL2XP1 Y * log{2}(X + 1)
3529 Constant Instructions
3530 Each of these instructions (table 2-10) loads (pushes) a commonly-used
3531 constant onto the stack. The values have full temporary real precision (64
3532 bits) and are accurate to approximately 19 decimal digits. Because a
3533 temporary real constant occupies 10 memory bytes, the constant
3534 instructions, which are only two bytes long, save storage and improve
3535 execution speed, in addition to simplifying programming.
3538 FLDZ (load zero) loads (pushes) +0.0 onto the stack.
3541 FLD1 (load one) loads (pushes) +1.0 onto the stack.
3544 FLDPI (load Ò) loads (pushes) Ò onto the stack.
3547 FLDL2T (load log base 2 of 10) loads (pushes) the value LOG{2}10 onto the
3551 FLDL2E (load log base 2 of e) loads (pushes) the value LOG{2}e onto the
3555 FLDLG2 (load log base 10 of 2) loads (pushes) the value LOG{10}2 onto the
3559 FLDLN2 (load log base e of 2) loads (pushes) the value LOG{e}2 onto the
3563 Table 2-10. Constant Instructions
3568 FLDL2T Load log{2}10
3570 FLDLG2 Load log{10}2
3574 Processor Control Instructions
3575 The processor control instructions shown in table 2-11 are not typically
3576 used in calculations; they provide control over the 80287 NPX for
3577 system-level activities. These activities include initialization, exception
3578 handling, and task switching.
3580 As shown in table 2-11, many of the NPX processor control instructions have
3581 two forms of assembler mnemonic:
3583 Ž A wait form, where the mnemonic is prefixed only with an F, such as
3584 FSTSW. This form checks for unmasked numeric errors.
3586 Ž A no-wait form, where the mnemonic is prefixed with an FN, such as
3587 FNSTSW. This form ignores unmasked numeric errors.
3589 When the control instruction is coded using the no-wait form of the
3590 mnemonic, the ASM286 assembler does not precede the ESC instruction with a
3591 wait instruction, and the CPU does not test the ERROR status line from the
3592 NPX before executing the processor control instruction.
3594 Only the processor control class of instructions have this alternate
3595 no-wait form. All numeric instructions are automatically synchronized by the
3596 80286, with the CPU testing the BUSY status line and only executing the
3597 numeric instruction when this line is inactive. Because of this automatic
3598 synchronization by the 80286, numeric instructions for the 80287 need not be
3599 preceded by a CPU wait instruction in order to execute correctly.
3601 It should also be noted that the 8087 instructions FENI and FDISI perform
3602 no function in the 80287. If these opcodes are detected in an 80286/80287
3603 instruction stream, the 80287 will perform no specific operation and no
3604 internal states will be affected. For programmers interested in porting
3605 numeric software from 8087 environments to the 80286, however, it should be
3606 noted that program sections containing these exception-handling instructions
3607 are not likely to be completely portable to the 80287. Appendix B contains
3608 a more complete description of the differences between the 80287 and the
3612 Table 2-11. Processor Control Instructions
3614 FINIT/FNINIT Initialize processor
3615 FSETPM Set Protected Mode
3616 FLDCW Load control word
3617 FSTCW/FNSTCW Store control word
3618 FSTSW/FNSTSW Store status word
3619 FSTSW AX/FNSTSW AX Store status word to AX
3620 FCLEX/FNCLEX Clear exceptions
3621 FSTENV/FNSTENV Store Environment
3622 FLDENV Load environment
3623 FSAVE/FNSAVE Save state
3624 FRSTOR Restore state
3625 FINCSTP Increment stack pointer
3626 FDECSTP Decrement stack pointer
3633 FINIT/FNINIT (initialize processor) sets the 80287 NPX into a known state,
3634 unaffected by any previous activity. The no-wait form of this instruction
3635 will cause the 80287 to abort any previous numeric operations currently
3636 executing in the NEU. This instruction performs the functional equivalent
3637 of a hardware RESET, with one exception; FINIT/FNINIT does not affect the
3638 current 80287 operating mode (either Real-Address mode or Protected mode).
3639 FINIT checks for unmasked numeric exceptions, FNINIT does not.
3641 Note that if FNINIT is executed while a previous 80287 memory-referencing
3642 instruction is running, 80287 bus cycles in progress will be aborted. This
3643 instruction may be necessary to clear the 80287 if a Processor Extension
3644 Segment Overrun Exception (Interrupt 9) is detected by the CPU.
3648 FSETPM (set Protected mode) sets the operating mode of the 80287 to
3649 Protected Virtual-Address mode. When the 80287 is first initialized
3650 following hardware RESET, it operates in Real-Address mode, just as does the
3651 80286 CPU. Once the 80287 NPX has been set into Protected mode, only a
3652 hardware RESET can return the NPX to operation in Real-Address mode.
3654 When the 80287 operates in Protected mode, the NPX exception pointers are
3655 represented differently than they are in Real-Address mode (see the FSAVE
3656 and FSTENV instructions that follow). This distinction is evident primarily
3657 to writers of numeric exception handlers, however. For general application
3658 programmers, the operating mode of the 80287 need not be a concern.
3662 FLDCW (load control word) replaces the current processor control word with
3663 the word defined by the source operand. This instruction is typically used
3664 to establish or change the 80287's mode of operation. Note that if an
3665 exception bit in the status word is set, loading a new control word that
3666 unmasks that exception and clears the interrupt enable mask will generate an
3667 immediate interrupt request before the next instruction is executed. When
3668 changing modes, the recommended procedure is to first clear any exceptions
3669 and then load the new control word.
3672 FSTCW/FNSTCW destination
3673 FSTCW/FNSTCW (store control word) writes the current processor control word
3674 to the memory location defined by the destination. FSTCW checks for unmasked
3675 numeric exceptions, FNSTCW does not.
3678 FSTSW/FNSTSW destination
3679 FSTSW/FNSTCW (store status word) writes the current value of the 80287
3680 status word to the destination operand in memory. The instruction is used to
3682 Ž Implement conditional branching following a comparison or FPREM
3685 Ž Poll the 80287 to determine if it is busy (FNSTSW)
3687 Ž Invoke exception handlers in environments that do not use interrupts
3690 FSTSW checks for unmasked numeric exceptions, FNSTSW does not.
3694 FSTSW AX/FNSTSW AX (store status word to AX) is a special 80287 instruction
3695 that writes the current value of the 80287 status word directly into the
3696 80286 AX register. This instruction optimizes conditional branching in
3697 numeric programs, where the 80286 CPU must test the condition of various NPX
3698 status bits. The waited form checks for unmasked numeric exceptions, the
3699 non-waited for does not.
3701 When this instruction is executed, the 80286 AX register is updated with
3702 the NPX status word before the CPU executes any further instructions. In
3703 this way, the 80286 can immediately test the NPX status word without any
3704 WAIT or other synchronization instructions required.
3708 FCLEX/FNCLEX (clear exceptions) clears all exception flags, the error
3709 status flag and the busy flag in the status word. As a consequence, the
3710 80287's ERROR line goes inactive. FCLEX checks for unmasked numeric
3711 exceptions, FNCLEX does not.
3714 FSAVE/FNSAVE destination
3715 FSAVE/FNSAVE (save state) writes the full 80287 state‘‘environment plus
3716 register stack‘‘to the memory location defined by the destination operand.
3717 Figure 2-1 shows the layout of the 94-byte save area; typically the
3718 instruction will be coded to save this image on the CPU stack. FNSAVE
3719 delays its execution until all NPX activity completes normally. Thus, the
3720 save image reflects the state of the NPX following the completion of any
3721 running instruction. After writing the state image to memory, FSAVE/FNSAVE
3722 initializes the 80287 as if FINIT/FNINIT had been executed.
3724 FSAVE/FNSAVE is useful whenever a program wants to save the current state
3725 of the NPX and initialize it for a new routine. Three examples are
3727 Ž An operating system needs to perform a context switch (suspend the
3728 task that had been running and give control to a new task).
3730 Ž An exception handler needs to use the 80287.
3732 Ž An application task wants to pass a "clean" 80287 to a subroutine.
3734 FSAVE checks for unmasked numeric errors before executing, FNSAVE does not.
3735 An FWAIT should be executed before CPU interrupts are enabled or any
3736 subsequent 80287 instruction is executed. Other CPU instructions may be
3737 executed between the FNSAVE/FSAVE and the FWAIT.
3740 Figure 2-1. FSAVE/FRSTOR Memory Layout
3742 \x11‘‘‘‘‘‘‘‘‘‘‘‘“INCREASING
3743 ‚�������������������������ƒ �ADDRESS
3744 REAL MODE € CONTROL WORD € +0 �
3745 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ �
3746 € STATUS WORD € +2 �
3747 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
\x1f
3749 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3750 ’‘€INSTRUCTION POINTER(15-0)€ +6
3751 � Ñ‘‘‘‘‘‘‘‘‘‘˜‘˜‘‘‘‘‘‘‘‘‘‘‘Â
3752 INSTRUCTION� €INSTRUCTION� �INSTRUCTION€
3753 POINTER— € POINTER �0� OPCODE € +8
3754 � € (19-14) � � (10-0) €
3755 ã�Ñ‘‘‘‘‘‘‘‘‘‘™‘™‘‘‘‘‘‘‘‘‘‘‘Â
3756 OPERAND� € DATA POINTER(15-0) € +10
3757 POINTER— Ñ‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3759 ”‘€ POINTER � 0 € +12
3761 „��ˆ��������¤����������ˆ��…
3762 ’‘€ SIGNIFICAND 15-0 € +14
3763 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3764 � € SIGNIFICAND 31-16 € +16
3765 TOP STACK— Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3766 ELEMENT:ST� € SIGNIFICAND 47-32 € +18
3767 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3768 � € SIGNIFICAND 63-48 € +20
3769 � Ñ
\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3770 ”‘€S� EXPONENT 14-0 € +22
3771 Ñ™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3772 ’‘€ SIGNIFICAND 15-0 € +14
3773 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3774 � € SIGNIFICAND 31-16 € +16
3775 NEXT STACK— Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3776 ELEMENT:ST(1)� € SIGNIFICAND 47-32 € +18
3777 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3778 � € SIGNIFICAND 63-48 € +20
3779 � Ñ
\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3780 ”‘€S� EXPONENT 14-0 € +22
3781 Ñ™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3782 Ñ™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3784 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3785 ’‘€ SIGNIFICAND 15-0 € +84
3786 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3787 � € SIGNIFICAND 31-16 € +86
3788 LAST STACK— Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3789 ELEMENT:ST(7)� € SIGNIFICAND 47-32 € +88
3790 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3791 � € SIGNIFICAND 63-48 € +90
3792 � Ñ
\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3793 ”‘€S� EXPONENT 14-0 € +92
3794 „�¤�����������������…
3797 \x11‘‘‘‘‘‘‘‘‘‘‘‘“INCREASING
3799 ‚���������������������ƒ �
3800 PROTECTED MODE € CONTROL WORD € +0 �
3801 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ �
3802 € STATUS WORD € +2 �
3803 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
\x1f
3805 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3807 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3809 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3810 € DATA OPERAND OFFSET € +10
3811 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3812 €DATA OPERAND SELECTOR€ +12
3813 „ˆ�������������������ˆ…
3814 ’‘€ SIGNIFICAND 15-0 € +14
3815 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3816 � € SIGNIFICAND 31-16 € +16
3817 TOP STACK— Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3818 ELEMENT:ST� € SIGNIFICAND 47-32 € +18
3819 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3820 � € SIGNIFICAND 63-48 € +20
3821 � Ñ
\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3822 ”‘€S� EXPONENT 14-0 € +22
3823 Ñ™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3824 ’‘€ SIGNIFICAND 15-0 € +24
3825 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3826 � € SIGNIFICAND 31-16 € +26
3827 NEXT STACK— Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3828 ELEMENT:ST(1)� € SIGNIFICAND 47-32 € +28
3829 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3830 � € SIGNIFICAND 63-48 € +30
3831 � Ñ
\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3832 ”‘€S� EXPONENT 14-0 € +32
3833 Ñ™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3835 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3836 € SIGNIFICAND 15-0 € +84
3837 ’‘Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3838 � € SIGNIFICAND 31-16 € +86
3839 � Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3840 LAST STACK— € SIGNIFICAND 47-32 € +88
3841 ELEMENT:ST(7)� Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3842 � € SIGNIFICAND 63-48 € +90
3843 � Ñ
\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3844 � €S� EXPONENT 14-0 € +92
3845 ”‘„�¤�����������������…
3847 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3849 a = INSTRUCTION POINTER
3852 Bit 0 of each field is rightmost, least significant
3853 bit of corresponding register field.
3854 Bit 63 of significand is integer bit (assumed
3855 binary point is immediately to the right.)
3856 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3860 FRSTOR (restore state) reloads the 80287 from the 94-byte memory area
3861 defined by the source operand. This information should have been written by
3862 a previous FSAVE/FNSAVE instruction and not altered by any other
3863 instruction. An FWAIT is not required after FRSTOR. FRSTOR will
3864 automatically wait and check for interrupts until all data transfers are
3865 completed before continuing to the next instruction.
3867 Note that the 80287 "reacts" to its new state at the conclusion of the
3868 FRSTOR; it will, for example, generate an exception request if the exception
3869 and mask bits in the memory image so indicate when the next WAIT or
3870 error-checking-ESC instruction is executed.
3873 FSTENV/FNSTENV destination
3874 FSTENV/FNSTENV (store environment) writes the 80287's basic
3875 status‘‘control, status, and tag words, and exception pointers‘‘to the
3876 memory location defined by the destination operand. Typically, the
3877 environment is saved on the CPU stack. FSTENV/FNSTENV is often used by
3878 exception handlers because it provides access to the exception pointers that
3879 identify the offending instruction and operand. After saving the
3880 environment, FSTENV/FNSTENV sets all exception masks in the processor.
3881 FSTENV checks for pending errors before executing, FNSTENV does not.
3883 Figure 2-2 shows the format of the environment data in memory. FNSTENV does
3884 not store the environment until all NPX activity has completed. Thus, the
3885 data saved by the instruction reflects the 80287 after any previously
3886 decoded instruction has been executed. After writing the environment image
3887 to memory, FNSTENV/FSTENV initializes the 80287 state as if FNINIT/FINIT
3890 FSTENV/FNSTENV must be allowed to complete before any other 80287
3891 instruction is decoded. When FSTENV is coded, an explicit FWAIT, or
3892 assembler-generated WAIT, should precede any subsequent 80287 instruction.
3895 Figure 2-2. FSTENV/FLDENV Memory Layout
3897 REAL MODE PROTECTED MODE
3898 15 0 MEMORY 15 0 MEMORY
3899 ‚�������������������������������ƒOFFSET ‚���������������������������ƒOFFSET
3900 € CONTROL WORD € +0 € CONTROL WORD € +0
3901 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3902 € STATUS WORD € +2 € STATUS WORD € +2
3903 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3904 € TAG WORD € +4 € TAG WORD € +4
3905 Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3906 € INSTRUCTION POINTER(15-0) € +6 € IP OFFSET € +6
3907 Ñ‘‘‘‘‘‘‘‘‘‘˜‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3908 €INSTRUCTION� � INSTRUCTION € € €
3909 € POINTER �0� OPCODE € +8 € CS SELECTOR € +8
3910 € (19-14) � � (10-0) € € €
3911 Ñ‘‘‘‘‘‘‘‘‘‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3912 € DATA POINTER(15-0) € +10 € DATA OPERAND OFFSET € +10
3913 Ñ‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3915 € POINTER � 0 € +12 € DATA OPERAND SELECTOR € +12
3917 „�����������¤�������������������… „���������������������������…
3922 FLDENV (load environment) reloads the environment from the memory area
3923 defined by the source operand. This data should have been written by a
3924 previous FSTENV/FNSTENV instruction. CPU instructions (that do not reference
3925 the environment image) may immediately follow FLDENV. An FWAIT is not
3926 required after FLDENV. FLDENV will automatically wait for all data
3927 transfers to complete before executing the next instruction.
3929 Note that loading an environment image that contains an unmasked exception
3930 will cause a numeric exception when the next WAIT or error-checking-ESC
3931 instruction is executed.
3935 FINCSTP (increment stack pointer) adds 1 to the stack top pointer (ST) in
3936 the status word. It does not alter tags or register contents, nor does it
3937 transfer data. It is not equivalent to popping the stack, because it does
3938 not set the tag of the previous stack top to empty. Incrementing the stack
3939 pointer when ST = 7 produces ST = 0.
3943 FDECSTP (decrement stack pointer) subtracts 1 from ST, the stack top
3944 pointer in the status word. No tags or registers are altered, nor is any
3945 data transferred. Executing FDECSTP when ST = 0 produces ST = 7.
3949 FFREE (free register) changes the destination register's tag to empty; the
3950 content of the register is unaffected.
3954 FNOP (no operation) stores the stack top to the stack top (FST ST,ST(0))
3955 and thus effectively performs no operation.
3958 FWAIT (CPU Instruction)
3959 FWAIT is not actually an 80287 instruction, but an alternate mnemonic for
3960 the CPU WAIT instruction. The FWAIT or WAIT mnemonic should be coded
3961 whenever the programmer wants to synchronize the CPU to the NPX, that is, to
3962 suspend further instruction decoding until the NPX has completed the current
3963 instruction. FWAIT will check for unmasked numeric exceptions.
3965 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3967 A CPU instruction should not attempt to access a memory operand until the
3968 80287 instruction has completed. For example, the following coding shows
3969 how FWAIT can be used to force the CPU instruction to wait for the 80287:
3972 FWAIT ; Wait for FIST to complete
3974 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3976 More information on when to code an FWAIT instruction is given in a
3977 following section of this chapter, "Concurrent Processing with the 80287."
3980 Instruction Set Reference Information
3981 Table 2-14 later in this chapter lists the operating characteristics of all
3982 the 80287 instructions. There is one table entry for each instruction
3983 mnemonic; the entries are in alphabetical order for quick lookup. Each entry
3984 provides the general operand forms accepted by the instruction as well as a
3985 list of all exceptions that may be detected during the operation.
3987 One entry exists for each combination of operand types that can be coded
3988 with the mnemonic. Table 2-12 explains the operand identifiers allowed in
3989 table 2-14. Following this entry are columns that provide execution time in
3990 clocks, the number of bus transfers run during the operation, the length of
3991 the instruction in bytes, and an ASM286 coding sample.
3994 Instruction Execution Time
3995 The execution of an 80287 instruction involves three principal activities,
3996 each of which may contribute to the overall execution time of the
3999 Ž 80286 CPU overhead involved in handling the ESC instruction opcode
4000 and setting up the 80287 NPX
4002 Ž Instruction execution by the 80287 NPX
4004 Ž Operand transfers between the 80287 NPX and memory or a CPU register
4006 The timing of these various activities is affected by the individual clock
4007 frequencies of the 80286 CPU and the 80287 NPX. In addition, slow memories
4008 requiring the insertion of wait states in bus cycles, and bus contention due
4009 to other processors in the system, may lengthen operand transfer times.
4011 In calculating an overall execution time for an individual numeric
4012 instruction, analysts must take each of these activities into account. In
4013 most cases, it can be assumed that the numeric instructions have already
4014 been prefetched by the 80286 and are awaiting execution.
4016 Ž The CPU overhead in handling the ESC instruction opcode takes only a
4017 single CPU bus cycle before the 80287 begins its execution of the
4018 numeric instruction. The timing of this bus cycle is determined by the
4019 CPU clock. Additional CPU activity is required to set up the 80287's
4020 instruction and data pointer registers, but this activity occurs after
4021 the 80287 has begun executing its instruction, and so this parallel
4022 activity does not affect total execution time.
4024 Ž The duration of individual numeric instructions executing on the 80287
4025 varies for each instruction. Table 2-14 quotes a typical execution
4026 clock count and a range for each 80287 instruction. Dividing the
4027 figures in the table by 10 (for a 10-MHz 80287 NPX clock) produces an
4028 execution time in microseconds. The typical case is an estimate for
4029 operand values that normally characterize most applications. The range
4030 encompasses best- and worst-case operand values that may be found in
4031 extreme circumstances.
4033 Ž The operand transfer time required to transfer operands between the
4034 80287 and memory or a CPU register depends on the number of words to be
4035 transferred, the frequency of the CPU clock controlling bus timing, the
4036 number of wait states added to accommodate slower memories, and
4037 whether operands are based at even or odd memory addresses. Some
4038 (small) additional number of bus cycles may also be lost due to the
4039 asynchronous nature of the PEREQ/PEACK handshaking between the 80286
4040 and 80287, and this interaction varies with relative frequencies of
4041 the CPU and NPX clocks.
4043 The execution clock counts for the NPX execution of instructions shown in
4044 table 2-14 assume that no exceptions are detected during execution. Invalid
4045 operation, denormalized operand (unmasked), and zero divide exceptions
4046 usually decrease execution time from the typical figure, but execution
4047 still falls within the indicated range. The precision exception has no
4048 effect on execution time. Unmasked overflow and underflow, and masked
4049 denormalized exceptions impose additional execution penalties as shown in
4050 table 2-13. Absolute worst-case execution times are therefore the high
4051 range figure plus the largest penalty that may be encountered.
4054 Table 2-12. Key to Operand Types
4057 Identifier Explanation
4059 ST Stack top; the register currently at the top of the stack.
4061 ST(i) A register in the stack i (0¾i¾7) stack elements from the
4062 top. ST(1) is the next-on-stack register, ST(2) is below
4065 Short-real A short real (32 bits) number in memory.
4067 Long-real A long real (64 bits) number in memory.
4069 Temp-real A temporary real (80 bits) number in memory.
4071 Packed-decimal A packed decimal integer (18 digits, 10 bytes) in memory.
4073 Word-integer A word binary integer (16 bits) in memory.
4075 Short-integer A short binary integer (32 bits) in memory.
4077 Long-integer A long binary integer (64 bits) in memory.
4079 nn-bytes A memory area nn bytes long.
4083 NPX instructions that reference memory require bus cycles to transfer
4084 operands between the NPX and memory. The actual number of transfers depends
4085 on the length of the operand and the alignment of the operand in memory.
4086 In table 2-14, the first figure gives execution clocks for even-addressed
4087 operands, while the second gives the clock count for odd-addressed operands.
4089 For operands aligned at word boundaries, that is, based at even memory
4090 addresses, each word to be transferred requires one bus cycle between the
4091 80286 data channel and memory, and one bus cycle to the NPX. For operands
4092 based at odd memory addresses, each word transfer requires two bus cycles
4093 to transfer individual bytes between the 80286 data channel and memory, and
4094 one bus cycle to the NPX.
4096 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4098 For best performance, operands for the 80287 should be aligned along word
4099 boundaries; that is, based at even memory addresses. Operands based at odd
4100 memory addresses are transferred to memory essentially byte-at-a-time and
4101 may take half again as long to transfer as word-aligned operands.
4102 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4104 Additional transfer time is required if slow memories are being used,
4105 requiring the insertion of wait states into the CPU bus cycle. In
4106 multiprocessor environments, the bus may not be available immediately; this
4107 overhead can also increase effective transfer time.
4110 Table 2-13. Execution Penalties
4112 Exception Additional Clocks
4113 Overflow (unmasked) 14
4114 Underflow (unmasked) 16
4115 Denormalized (masked) 33
4119 80287 instructions that do not reference memory are two bytes long. Memory
4120 reference instructions vary between two and four bytes. The third and fourth
4121 bytes are for the 8- or 16-bit displacement values used in conjunction with
4122 the standard 80286 memory-addressing modes.
4124 Note that the lengths quoted in table 2-14 for the processor control
4125 instructions (FNINIT, FNSTCW, FNSTSW, FNSTSW AX, FNCLEX, FNSTENV, and
4126 FNSAVE) do not include the one-byte CPU wait instruction inserted by the
4127 ASM286 assembler if the control instruction is coded using the wait form of
4128 the mnemonic (e.g. FINIT, FSTCW, FSTSW, FSTSW AX, FCLEX, FSTENV, and
4129 FSAVE). Wait and no-wait forms of the processor control instructions have
4130 been described in the preceding section titled "Processor Control
4134 Table 2-14. Instruction Set Reference Data
4137 ®Execution Clocks¬ Operand Word Code
4138 Operands Typical Range Transfers Bytes Coding Example
4139 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4140 FABS FABS (no operands)
4141 Absolute value Exceptions: I
4143 (no operands) 14 10-17 0 2 FABS
4144 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4145 FADD FADD\\source\destination,source
4146 Add real Execptions: I,D,O,U,P
4148 \\ST,ST(i)\ST(i),ST 85 70-100 0 2 FADD,ST,ST(4)
4149 short-real 105 90-120 2 2-4 FADD AIR_TEMP [SI]
4150 long-real 110 95-125 4 2-4 FADD [BX].MEAN
4151 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4152 FADDP FADDP destination, source
4153 Add real and pop Exceptions: I,D,O,U,P
4155 ST(i),ST 90 75-105 0 2 FADDP ST(2),ST
4156 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4158 Packed decimal (BCD) load Exceptions: I
4160 packed-decimal 300 290-310 5 2-4 FBLD YTD_SALES
4161 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4162 FBSTP FBSTP destination
4163 Packed decimal (BCD) store and pop Exceptions: I
4165 packed-decimal 530 520-540 5 2-4 FBSTP [BX].FORECAST
4166 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4167 FCHS FCHS (no operands)
4168 Change sign Exceptions: I
4169 (no operands) 15 10-17 0 2 FCHS
4170 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4171 FCLEX/FNCLEX FCLEX/FNCLEX(no operands)
4172 Clear exceptions Exceptions: None
4174 (no operands) 5 2-8 0 2 FNCLEX
4175 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4177 Compare real Exceptions: I, D
4179 //ST(i) 45 40-50 0 2 FCOM ST(1)
4180 short-real 65 60-70 2 2-4 FCOM [BP].UPPER_LIMIT
4181 long-real 70 65-75 4 2-4 FCOM WAVELENGTH
4182 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4183 FCOMP FCOMP //source
4184 Compare real and pop Exceptions: I, D
4186 //ST(i) 47 42-52 0 2 FCOMP ST(2)
4187 short-real 68 63-73 2 2-4 FCOMP [BP + 2].N_READINGS
4188 long-real 72 67-77 4 2-4 FCOMP DENSITY
4189 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4190 FCOMPP FCOMPP (no operands)
4191 Compare real and pop twice Exceptions: I, D
4193 (no operands) 50 45-55 0 2 FCOMPP
4194 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4195 FDECSTP FDECSTP (no operands)
4196 Decrement stack pointer Exceptions: None
4198 (no operands) 9 6-12 0 2 FDECSTP
4199 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4200 FDIV FDIV //source/destination,source
4201 Divide real Exceptions: I, D, Z, O, U, P
4203 //ST(i),ST 198 193-203 0 2 FDIV
4204 short-real 220 215-225 2 2-4 FDIV DISTANCE
4205 long-real 225 220-230 4 2-4 FDIV ARC [DI]
4206 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4207 FDIVP FDIVP destination, source
4208 Divide real and pop Exceptions: I, D, Z, O, U, P
4210 ST(i),ST 202 197-207 0 2 FDIVP ST(4),ST
4211 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4212 FDIVR FDIVR //source/destination, source
4213 Divide real reversed Exceptions: I, D, Z, O, U, P
4215 //ST,ST(i)/ST(i),ST 199 194-204 0 2 FDIVR ST(2),ST
4216 short-real 221 216-226 2 2-4 FDIVR [BX].PULSE_RATE
4217 long-real 226 221-231 4 2-4 FDIVR RECORDER.FREQUENCY
4218 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4219 FDIVRP FDIVRP destination, source
4220 Divide real reversed and pop Exceptions: I, D, Z, O, U, P
4222 ST(i),ST 203 198-208 0 2 FDIVRP ST(1),ST
4223 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4224 FFREE FFREE destination
4225 Free register Exceptions: None
4227 ST(i) 11 9-16 0 2 FFREE ST(1)
4228 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4230 Integer add Exceptions: I, D, O, P
4232 word-integer 120 102-137 1 2-4 FIADD DISTANCE_TRAVELLED
4233 short-integer 125 108-143 2 2-4 FIADD PULSE_COUNT [SI]
4234 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4236 Integer compare Exceptions: I, D
4238 word-integer 80 72-86 1 2-4 FICOM TOOL.N_PASSES
4239 short-integer 85 78-91 2 2-4 FICOM [BP+4].PARM_COUNT
4240 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4241 FICOMP FICOMP source
4242 Integer compare and pop Exceptions: I, D
4244 word-integer 82 74-88 1 2-4 FICOMP [BP].LIMIT [SI]
4245 short-integer 87 80-93 2 2-4 FICOMP N_SAMPLES
4246 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4248 Integer divide Exceptions: I, D, Z, O, U, P
4250 word-integer 230 224-238 1 2-4 FIDIV SURVEY.OBSERVATIONS
4251 short-integer 236 230-243 2 2-4 FIDIV RELATIVE_ANGLE [DI]
4252 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4253 FIDIVR FIDIVR source
4254 Integer divide reversed Exceptions: I, D, Z, O, U, P
4256 word-integer 230 225-239 1 2-4 FIDIVR [BP].X_COORD
4257 short-integer 237 231-245 2 2-4 FIDIVR FREQUENCY
4258 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4260 Integer load Exceptions: I
4262 word-integer 50 46-54 1 2-4 FILD [BX].SEQUENCE
4263 short-integer 56 52-60 2 2-4 FILD STANDOFF [DI]
4264 long-integer 64 60-68 4 2-4 FILD RESPONSE.COUNT
4265 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4267 Integer multiply Exceptions: I, D, O, P
4269 word-integer 130 124-138 1 2-4 FIMUL BEARING
4270 short-integer 136 130-144 2 2-4 FIMUL POSITION.Z_AXIS
4271 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4272 FINCSTP FINCSTP (no operands)
4273 Increment stack pointer Exceptions: None
4275 (no operands) 9 6-12 0 2 FINCSTP
4276 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4277 FINIT/FNINIT FINIT/FNINIT (no operands)
4278 Initialize processor Exceptions: None
4280 (no operands) 5 2-8 0 2 FINIT
4281 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4282 FIST FIST destination
4283 Integer store Exceptions: I, P
4285 word-integer 86 80-90 1 2-4 FIST OBS.COUNT[SI]
4286 short-integer 88 82-92 2 2-4 FIST [BP;].FACTORED_PULSES
4287 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4288 FISTP FISTP destination
4289 Integer store and pop Exceptions: I, P
4291 word-integer 88 82-92 1 2-4 FISTP [BX].ALPHA_COUNT [SI]
4292 short-integer 90 84-94 2 2-4 FISTP CORRECTED_TIME
4293 long-integer 100 94-105 4 2-4 FISTP PANEL.N_READINGS
4294 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4296 Integer subtract Exceptions: I, D, O, P
4298 word-integer 120 102-137 1 2-4 FISUB BASE_FREQUENCY
4299 short-integer 125 108-143 2 2-4 FISUB TRAIN_SIZE [DI]
4300 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4301 FISUBR FISUBR source
4302 Integer subtract reversed Exceptions: I, D, O, P
4304 word-integer 120 103-139 1 2-4 FISUBR FLOOR [BX] [SI]
4305 short-integer 125 109-144 2 2-4 FISUBR BALANCE
4306 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4308 Load real Exceptions: I, D
4310 ST(i) 20 17-22 0 2 FLD ST(0)
4311 short-real 43 38-56 2 2-4 FLD READING [SI].PRESSURE
4312 long-real 46 40-60 4 2-4 FLD BP].TEMPERATURE
4313 temp-real 57 53-65 5 2-4 FLD SAVEREADING
4314 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4316 Load control word Exceptions: None
4318 2-bytes 10 7-14 1 2-4 FLDCW CONTROL_WORD
4319 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4320 FLDENV FLDENV source
4321 Load environment Exceptions: None
4323 14-bytes 40 35-45 7 2-4 FLDENV [BP + 6]
4324 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4325 FLDLG2 FLDLG2 (no operands)
4326 Load log{10}2 Exceptions: I
4328 (no operands) 21 18-24 0 2 FLDLG2
4329 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4330 FLDLN2 FLDLN2 (no operands)
4331 Load log{e}2 Exceptions: I
4333 (no operands) 20 17-23 0 2 FLDLN2
4334 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4335 FLDL2E FLDL2E (no operands)
4336 Load log{2}e Exceptions: I
4338 (no operands) 18 15-21 0 2 FLDL2E
4339 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4340 FLDL2T FLDL2T (no operands)
4341 Load log{2}10 Exceptions: I
4343 (no operands) 19 16-22 0 2 FLDL2T
4344 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4345 FLDPI FLDPI (no operands)
4346 Load Ò Exceptions: I
4348 (no operands) 19 16-22 0 2 FLDPI
4349 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4350 FLDZ FLDZ (no operands)
4351 Load +0.0 Exceptions: I
4353 (no operands) 14 11-17 0 2 FLDZ
4354 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4355 FLD1 FLD1 (no operands)
4356 Load +1.0 Exceptions: I
4358 (no operands) 18 15-21 0 2 FLD1
4359 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4360 FMUL FMUL //source/destination,source
4361 Multiply real Exceptions: I, D, O, U, P
4364 Occurs when one or both operands is "short"‘‘it has 40 trailing zeros
4365 in its fraction (e.g., it was loaded from a short-real memory operand). 97 90-105 0 2 FMUL ST,ST(3)
4366 //ST(i),ST/ST,ST(i) 138 130-145 0 2 FMUL ST,ST(3)
4367 short-real 118 110-125 2 2-4 FMUL SPEED_FACTOR
4369 Occurs when one or both operands is "short"‘‘it has 40 trailing zeros
4370 in its fraction (e.g., it was loaded from a short-real memory operand). 120 112-126 4 2-4 FMUL [BP].HEIGHT
4371 long-real 161 154-168 4 2-4 FMUL [BP].HEIGHT
4372 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4373 FMULP FMULP destination, source
4374 Multiply real and pop Exceptions: I, D, O, U, P
4377 Occurs when one or both operands is "short"‘‘it has 40 trailing zeros
4378 in its fraction (e.g., it was loaded from a short-real memory operand). 100 94-108 0 2 FMULP ST(1),ST
4379 ST(i),ST 142 134-148 0 2 FMULP ST(1),ST
4380 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4381 FNOP FNOP (no operands)
4382 No operation Exceptions: None
4384 (no operands) 13 10-16 0 2 FNOP
4385 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4386 FPATAN FPATAN (no operands)
4387 Partial arctangent Exceptions: U, P (operands not checked)
4389 (no operands) 650 250-800 0 2 FPATAN
4390 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4391 FPREM FPREM (no operands)
4392 Partial remainder Exceptions: I, D, U
4394 (no operands) 125 15-190 0 2 FPREM
4395 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4396 FPTAN FPTAN (no operands)
4397 Partial tangent Exceptions: I, P (operands not checked)
4399 (no operands) 450 30-540 0 2 FPTAN
4400 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4401 FRNDINT FRNDINT (no operands)
4402 Round to integer Exceptions: I, P
4404 (no operands) 45 16-50 0 2 FRNDINT
4405 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4406 FRSTOR FRSTOR source
4407 Restore saved state Exceptions: None
4410 The 80287 execution clock count for this instruction is not meaningful
4411 in determining overall instruction execution time. For typical frequency
4412 ratios of the 80286 and 80287 clocks, 80287 execution occurs in parallel
4413 with the operand transfers, with the operand transfers determining the
4414 overall execution time of the instruction. For 80286:80287 clock frequency
4415 ratios of 4:8, 1:1, and 8:5, the overall execution clock count for this
4416 instruction is estimated at 490, 302, and 227 80287 clocks, respectively.) 47 2-4 FRSTOR [BP]
4417 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4418 FSAVE/FNSAVE FSAVE/FNSAVE destination
4419 Save state Exceptions: None
4422 The 80287 execution clock count for this instruction is not meaningful in
4423 determining overall instruction execution time. For typical frequency
4424 rations of the 80286 and 80287 clocks, 80287 execution occurs in parallel
4425 with the operand transfers, with the operand transfers determining the
4426 overall execution time of the instruction. For 80286:80287 clock frequency
4427 ratios of 4:8, 1:1, and 8:5, the overall execution clock count for this
4428 instruction is estimated at 376, 233, and 174 80287 clocks, respectively.) 47 2-4 FSAVE [BP]
4429 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4430 FSCALE FSCALE (no operands)
4431 Scale Exceptions: I, O, U
4433 (no operands) 35 32-38 0 2 FSCALE
4434 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4435 FSETPM FSETPM (no operands)
4436 Set protected mode Exceptions: None
4438 (no operands) 2-8 0 2 FSETPM
4439 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4440 FSQRT FSQRT (no operands)
4441 Square root Exceptions: I, D, P
4443 (no operands) 183 80-186 0 2 FSQRT
4444 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4446 Store real Exceptions: I, O, U, P
4448 ST(i) 18 15-22 0 2 FST ST(3)
4449 short-real 87 84-90 2 2-4 FST CORRELATION [DI]
4450 long-real 100 96-104 4 2-4 FST MEAN_READING
4451 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4452 FSTCW/ FSTCW destination
4453 FNSTCW Store control word Exceptions: None
4455 2-bytes 15 12-18 1 2-4 FSTCW SAVE_CONTROL
4456 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4457 FSTENV/ FSTENV destination
4458 FNSTENV Store environment Exceptions: None
4460 14-bytes 45 40-50 7 2-4 FSTENV [BP]
4461 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4462 FSTP FSTP destination
4463 Store real and pop Exceptions: I, O, U, P
4465 ST(i) 20 17-24 0 2 FSTP ST(2)
4466 short-real 89 86-92 2 2-4 FSTP [BX].ADJUSTED_RPM
4467 long-real 102 98-106 4 2-4 FSTP TOTAL_DOSAGE
4468 temp-real 55 52-58 5 2-4 FSTP REG_SAVE [SI]
4469 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4470 FSTSW/ FSTSW destination
4471 FNSTSW Store status word Exceptions: None
4473 2-bytes 15 12-18 1 2-4 FSTSW SAVE_STATUS
4474 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4476 FNSTSWAX Store status word to AX Exceptions: None
4478 AX 10-16 1 2 FSTSW AX
4479 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4480 FSUB FSUB //source/destination,source
4481 Subtract real Exceptions: I, D, O, U, P
4483 //ST,ST(i)/ST(i),ST 85 70-100 0 2 FSUB ST,ST(2)
4484 short-real 105 90-120 2 2-4 FSUB BASE_VALUE
4485 long-real 110 95-125 4 2-4 FSUB COORDINATE.X
4486 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4487 FSUBP FSUBP destination, source
4488 Subtract real and pop Exceptions: I, D, O, U, P
4490 ST(i),ST 90 75-105 0 2 FSUBP ST(2),ST
4491 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4492 FSUBR FSUBR //source/destination, source
4493 Subtract real reversed Exceptions: I, D, O, U, P
4495 //ST,ST(i)/ST(i),ST 87 70-100 0 2 FSUBR ST,ST(1)
4496 short-real 105 90-120 2 2-4 FSUBR VECTOR[SI]
4497 long-real 110 95-125 4 2-4 FSUBR [BX].INDEX
4498 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4499 FSUBRP FSUBRP destination, source
4500 Subtract real reversed and pop Exceptions: I, D, O, U, P
4502 ST(i),ST 90 75-105 0 2 FSUBRP ST(1),ST
4503 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4504 FTST FTST (no operands)
4505 Test stack top against +0.0 Exceptions: I, D
4506 (no operands) 42 38-48 0 2 FTST
4507 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4508 FWAIT FWAIT (no operands)
4509 (CPU) Wait while 80287 is busy Exceptions: None (CPU instruction)
4512 n = number of times CPU examines BUSY line before 80287 completes
4513 execution of previous instruction. 3+5n
4514 n = number of times CPU examines BUSY line before 80287 completes
4515 execution of previous instruction. 0 1 FWAIT
4516 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4517 FXAM FXAM (no operands)
4518 Examine stack top Exceptions: None
4520 (no operands) 17 12-23 0 2 FXAM
4521 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4522 FXCH FXCH //destination
4523 Exchange registers Exceptions: I
4525 //ST(i) 12 10-15 0 2 FXCH ST(2)
4526 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4527 FXTRACT FXTRACT (no operands)
4528 Extract exponent and significant Exceptions: I
4530 (no operands) 50 27-55 0 2 FXTRACT
4531 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4532 FYL2X FYL2X (no operands)
4533 Y * Log{2}X Exceptions: P (operands not checked)
4535 (no operands) 950 900-1100 0 2 FYL2X
4536 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4537 FYL2XP1 FYL2XP1 (no operands)
4538 Y * log{2}(X + 1) Exceptions: P (operands not checked)
4540 (no operands) 850 700-1000 0 2 FYL2XP1
4541 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4542 F2XM1 F2XM1 (no operands)
4543 2^(2-1) Exceptions: U, P (operands not checked)
4545 (no operands) 500 310-630 0 2 F2XM1
4546 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4550 Programming Facilities
4551 As described previously, the 80287 NPX is programmed simply as an extension
4552 of the 80286 CPU. This section describes how programmers in ASM286 and in a
4553 variety of higher-level languages can work with the 80287.
4555 The level of detail in this section is intended to give programmers a basic
4556 understanding of the software tools that can be used with the 80287, but
4557 this information does not document the full capabilities of these
4558 facilities. For a complete list of documentation on all the languages
4559 available for 80286 systems, readers should consult Intel's Literature
4563 High-Level Languages
4564 For programmers using high-level languages, the programming and operation
4565 of the NPX is handled automatically by the compiler. A variety of Intel
4566 high-level languages are available that automatically make use of the 80287
4567 NPX when appropriate. These languages include
4574 Each of these high-level languages has special numeric libraries allowing
4575 programs to take advantage of the capabilities of the 80287 NPX. No special
4576 programming conventions are necessary to make use of the 80287 NPX when
4577 programming numeric applications in any of these languages.
4579 Programmers in PL/M-286 and ASM286 can also make use of many of these
4580 library routines by using routines contained in the 80287 Support Library,
4581 described in the 80287 Support Library Reference Manual, Order Number
4582 122129. These library routines provide many of the functions provided by
4583 higher-level languages, including exception handlers,
4584 ASCII-to-floating-point conversions, and a more complete set of
4585 transcendental functions than that provided by the 80287 instruction set.
4589 Programmers in PL/M-286 can access a very useful subset of the 80287's
4590 numeric capabilities. The PL/M-286 REAL data type corresponds to the NPX's
4591 short real (32-bit) format. This data type provides a range of about
4592 8.43*10^(-37) ¾ ABS(X) ¾ 3.38*10^(38), with about seven significant
4593 decimal digits. This representation is adequate for the data manipulated by
4594 many microcomputer applications.
4596 The utility of the REAL data type is extended by the PL/M-286 compiler's
4597 practice of holding intermediate results in the 80287's temporary real
4598 format. This means that the full range and precision of the processor are
4599 utilized for intermediate results. Underflow, overflow, and rounding errors
4600 are most likely to occur during intermediate computations rather than during
4601 calculation of an expression's final result. Holding intermediate results in
4602 temporary real format greatly reduces the likelihood of overflow and
4603 underflow and eliminates roundoff as a serious source of error until the
4604 final assignment of the result is performed.
4606 The compiler generates 80287 code to evaluate expressions that contain REAL
4607 data types, whether variables or constants or both. This means that
4608 addition, subtraction, multiplication, division, comparison, and assignment
4609 of REALs will be performed by the NPX. INTEGER expressions, on the other
4610 hand, are evaluated on the CPU.
4612 Five built-in procedures (table 2-15) give the PL/M-286 programmer access
4613 to 80287 functions manipulated by the processor control instructions. Prior
4614 to any arithmetic operations, a typical PL/M-286 program will set up the NPX
4615 after power up using the INIT$REAL$MATH$UNIT procedure and then issue
4616 SET$REAL$MODE to configure the NPX. SET$REAL$MODE loads the 80287 control
4617 word, and its 16-bit parameter has the format shown in figure 1-5. The
4618 recommended value of this parameter is 033EH (projective closure, round to
4619 nearest, 64-bit precision, all exceptions masked except invalid operation).
4620 Other settings may be used at the programmer's discretion.
4622 If any exceptions are unmasked, an exception handler must be provided in
4623 the form of an interrupt procedure that is designated to be invoked by CPU
4624 interrupt pointer (vector) number 16. The exception handler can use the
4625 GET$REAL$ERROR procedure to obtain the low-order byte of the 80287 status
4626 word and to then clear the exception flags. The byte returned by
4627 GET$REAL$ERROR contains the exception flags; these can be examined to
4628 determine the source of the exception.
4630 The SAVE$REAL$STATUS and RESTORE$REAL$STATUS procedures are provided for
4631 multi-tasking environments where a running task that uses the 80287 may be
4632 preempted by another task that also uses the 80287. It is the responsibility
4633 of the preempting task to issue SAVE$REAL$STATUS before it executes any
4634 statements that affect the 80287; these include the INIT$REAL$MATH$UNIT and
4635 SET$REAL$MODE procedures as well as arithmetic expressions.
4636 SAVE$REAL$STATUS saves the 80287 state (registers, status, and control
4637 words, etc.) on the CPU's stack. RESTORE$REAL$STATUS reloads the state
4638 information; the preempting task must invoke this procedure before
4639 terminating in order to restore the 80287 to its state at the time the
4640 running task was preempted. This enables the preempted task to resume
4641 execution from the point of its preemption.
4644 Table 2-15. PL/M-286 Built-In Procedures
4647 Procedure Instruction Description
4650 Also initializes interrupt pointers for emulation. FINIT Initialize processor.
4652 SET$REAL$MODE FLDCW Set exception masks, rounding
4653 precision, and infinity
4657 Returns low-order byte of status word. FNSTSW & FNCLEX Store, then clear, exception
4660 SAVE$REAL$STATUS FNSAVE Save processor state.
4662 RESTORE$REAL$STATUS FRSTOR Restore processor state.
4666 The ASM286 assembly language provides programmmers with complete access to
4667 all of the facilities of the 80286 and 80287 processors.
4669 The programmer's view of the 80286/80287 hardware is a single machine with
4674 Ž 8 general registers
4675 Ž 4 segment registers
4676 Ž 8 floating-point registers, organized as a stack
4680 The ASM286 directives shown in table 2-16 allocate storage for 80287
4681 variables and constants. As with other storage allocation directives, the
4682 assembler associates a type with any variable defined with these directives.
4683 The type value is equal to the length of the storage unit in bytes (10 for
4684 DT, 8 for DQ, etc.). The assembler checks the type of any variable coded in
4685 an instruction to be certain that it is compatible with the instruction. For
4686 example, the coding FIADD ALPHA will be flagged as an error if ALPHA's type
4687 is not 2 or 4, because integer addition is only available for word and
4688 short integer data types. The operand's type also tells the assembler which
4689 machine instruction to produce; although to the programmer there is only an
4690 FIADD instruction, a different machine instruction is required for each
4693 On occasion it is desirable to use an instruction with an operand that has
4694 no declared type. For example, if register BX points to a short integer
4695 variable, a programmer may want to code FIADD [BX]. This can be done by
4696 informing the assembler of the operand's type in the instruction, coding
4697 FIADD DWORD PTR [BX]. The corresponding overrides for the other storage
4698 allocations are WORD PTR, QWORD PTR, and TBYTE PTR.
4700 The assembler does not, however, check the types of operands used in
4701 processor control instructions. Coding FRSTOR [BP] implies that the
4702 programmer has set up register BP to point to the stack location where the
4703 processor's 94-byte state record has been previously saved.
4705 The initial values for 80287 constants may be coded in several different
4706 ways. Binary integer constants may be specified as bit strings, decimal
4707 integers, octal integers, or hexadecimal strings. Packed decimal values are
4708 normally written as decimal integers, although the assembler will accept
4709 and convert other representations of integers. Real values may be written as
4710 ordinary decimal real numbers (decimal point required), as decimal numbers
4711 in scientific notation, or as hexadecimal strings. Using hexadecimal strings
4712 is primarily intended for defining special values such as infinities, NaNs,
4713 and nonnormalized numbers. Most programmers will find that ordinary decimal
4714 and scientific decimal provide the simplest way to initialize 80287
4715 constants. Figure 2-3 compares several ways of setting the various 80287
4716 data types to the same initial value.
4718 Note that preceding 80287 variables and constants with the ASM286 EVEN
4719 directive ensures that the operands will be word-aligned in memory. This
4720 will produce the best system performance. All 80287 data types occupy
4721 integral numbers of words so that no storage is "wasted" if blocks of
4722 variables are defined together and preceded by a single EVEN declarative.
4725 Table 2-16. 80287 Storage Allocation Directives
4727 Directive Interpretation Data Types
4729 DW Define Word Word integer
4730 DD Define Doubleword Short integer, short real
4731 DQ Define Quadword Long integer, long real
4732 DT Define Tenbyte Packed decimal, temporary real
4735 Records and Structures
4736 The ASM286 RECORD and STRUC (structure) declaratives can be very useful in
4737 NPX programming. The record facility can be used to define the bit fields of
4738 the control, status, and tag words. Figure 2-4 shows one definition of the
4739 status word and how it might be used in a routine that polls the 80287 until
4740 it has completed an instruction.
4742 Because STRUCtures allow different but related data types to be grouped
4743 together, they often provide a natural way to represent "real world" data
4744 organizations. The fact that the structure template may be "moved" about in
4745 memory adds to its flexibility. Figure 2-5 shows a simple structure that
4746 might be used to represent data consisting of a series of test score
4747 samples. A structure could also be used to define the organization of the
4748 information stored and loaded by the FSTENV and FLDENV instructions.
4751 Figure 2-3. Sample 80287 Constants
4753 ; THE FOLLOWING ALL ALLOCATE THE CONSTANT: -126
4754 ; NOTE TWO'S COMPLETE STORAGE OF NEGATIVE BINARY INTEGERS.
4756 EVEN ; FORCE WORK ALIGNMENT
4757 WORD_INTEGER DW 111111111000010B ; BIT STRING
4758 SHORT_INTEGER DD OFFFFFF82H ; HEX STRING MUST START
4760 LONG_INTEGER DQ -126 ; ORDINARY DECIMAL
4761 SHORT_REAL DD -126.0 ; NOTE PRESENCE OF '.'
4762 LONG_REAL DD -1.26E2 ; "SCIENTIFIC"
4763 PACKED_DECIMAL DT -126 ; ORDINARY DECIMAL INTEGER
4765 ; IN THE FOLLOWING, SIGN AND EXPONENT IS 'C005'
4766 ; SIGNIFICAND IS '7E00...00', 'R' INFORMS ASSEMBLER THAT
4767 ; THE STRING REPRESENTS A REAL DATA TYPE.
4769 TEMP_REAL DT 0C0057E00000000000000R ; HEX STRING
4772 Figure 2-4. Status Word RECORD Definition
4774 ; RESERVE SPACE FOR STATUS WORD
4776 ; LAY OUT STATUS WORD FIELDS
4792 ; POLL STATUS WORD UNTIL 80287 IS NOT BUSY
4793 POLL: FNSTSW STATUS_WORD
4794 TEST STATUS_WORD, MASK_BUSY
4798 Figure 2-5. Structure Definition
4802 N_OBS DD ? ; SHORT INTEGER
4803 MEAN DQ ? ; LONG REAL
4804 MODE DW ? ; WORD INTEGER
4805 STD_DEV DQ ? ; LONG REAL
4806 ; ARRAY OF OBSERVATIONS -- WORD INTEGER
4807 TEST_SCORES DW 1000 DUP (?)
4812 80287 memory data can be accessed with any of the CPU's five memory
4813 addressing modes. This means that 80287 data types can be incorporated in
4814 data aggregates ranging from simple to complex according to the needs of the
4815 application. The addressing modes, and the ASM286 notation used to specify
4816 them in instructions, make the accessing of structures, arrays, arrays of
4817 structures, and other organizations direct and straightforward. Table 2-17
4818 gives several examples of 80287 instructions coded with operands that
4819 illustrate different addressing modes.
4822 Table 2-17. Addressing Mode Examples
4824 ’‘‘‘ Coding‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ Interpretation
4826 FIADD ALPHA ALPHA is a simple scalar (mode is direct).
4828 FDIVR ALPHA.BETA BETA is a field in a structure that is
4829 "overlaid" on ALPHA (mode is direct).
4831 FMUL QWORD PTR [BX] BX contains the address of a long real
4832 variable (mode is register indirect).
4834 FSUB ALPHA [SI] ALPHA is an array and SI contains the
4835 offset of an array element from the start of
4836 the array (mode is indexed).
4838 FILD [BP].BETA BP contains the address of a structure on
4839 the CPU stack and BETA is a field in the
4840 structure (mode is based).
4842 FBLD TBYTE PTR [BX] [DI] BX contains the address of a packed
4843 decimal array and DI contains the offset of
4844 an array element (mode is based indexed).
4847 Comparative Programming Example
4848 Figures 2-6 and 2-7 show the PL/M-286 and ASM286 code for a simple 80287
4849 program, called ARRSUM. The program references an array (X$ARRAY), which
4850 contains 0-100 short real values; the integer variable N$OF$X indicates the
4851 number of array elements the program is to consider. ARRSUM steps through
4852 X$ARRAY accumulating three sums:
4854 Ž SUM$X, the sum of the array values
4856 Ž SUM$INDEXES, the sum of each array value times its index, where the
4857 index of the first element is 1, the second is 2, etc.
4859 Ž SUM$SQUARES, the sum of each array element squared
4861 (A true program, of course, would go beyond these steps to store and use
4862 the results of these calculations.) The control word is set with the
4863 recommended values: projective closure, round to nearest, 64-bit precision,
4864 interrupts enabled, and all exceptions masked invalid operation. It is
4865 assumed that an exception handler has been written to field the invalid
4866 operation, if it occurs, and that it is invoked by interrupt pointer 16.
4867 Either version of the program will run on an actual or an emulated 80287
4868 without altering the code shown.
4870 The PL/M-286 version of ARRSUM (figure 2-6) is very straightforward and
4871 illustrates how easily the 80287 can be used in this language. After
4872 declaring variables the program calls built-in procedures to initialize the
4873 processor (or its emulator) and to load to the control word. The program
4874 clears the sum variables and then steps through X$ARRAY with a DO-loop. The
4875 loop control takes into account PL/M-286's practice of considering the index
4876 of the first element of an array to be 0. In the computation of SUM$INDEXES,
4877 the built-in procedure FLOAT converts I+1 from integer to real because the
4878 language does not support "mixed mode" arithmetic. One of the strengths of
4879 the NPX, of course, is that it does support arithmetic on mixed data types
4880 (because all values are converted internally to the 80-bit temporary real
4883 The ASM286 version (figure 2-7) defines the external procedure INIT287,
4884 which makes the different initialization requirements of the processor and
4885 its emulator transparent to the source code. After defining the data and
4886 setting up the segment registers and stack pointer, the program calls
4887 INIT287 and loads the control word. The computation begins with the next
4888 three instructions, which clear three registers by loading (pushing) zeros
4889 onto the stack. As shown in figure 2-8, these registers remain at the
4890 bottom of the stack throughout the computation while temporary values are
4891 pushed on and popped off the stack above them.
4893 The program uses the CPU LOOP instruction to control its iteration through
4894 X_ARRAY; register CX, which LOOP automatically decrements, is loaded with
4895 N_OF_X, the number of array elements to be summed. Register SI is used to
4896 select (index) the array elements. The program steps through X_ARRAY from
4897 back to front, so SI is initialized to point at the element just beyond the
4898 first element to be processed. The ASM286 TYPE operator is used to determine
4899 the number of bytes in each array element. This permits changing X_ARRAY to
4900 a long real array by simply changing its definition (DD to DQ) and
4903 Figure 2-8 shows the effect of the instructions in the program loop on the
4904 NPX register stack. The figure assumes that the program is in its first
4905 iteration, that N_OF_X is 20, and that X_ARRAY(19) (the 20th element)
4906 contains the value 2.5. When the loop terminates, the three sums are left
4907 as the top stack elements so that the program ends by simply popping them
4908 into memory variables.
4911 Figure 2-6. Sample PL/M-286 Program
4913 PL/M-286 COMPILER ARRAYSUM
4915 SERIES-III PL/M-286 V 1.0 COMPILATION OF MODULE ARRAYSUM
4916 OBJECT MODULE PLACED IN :F6:D.OBJ
4917 COMPILER INVOLKED BY PLM286.86 :F6:D.SRC XREF
4919 /******************************************
4923 ******************************************/
4927 2 1 declare (sum$x,sum$indexes,sum$squares) real;
4928 3 1 declare x$array(100) real;
4929 4 1 declare (n$of$x,i) integer;
4930 5 1 declare control$287 literally '033eh';
4932 /* Assume x$array and n$of$x are initalized */
4934 /* Prepare the 80287 of its emulator */
4935 6 1 call init$real$math$unit;
4936 7 1 call set$real$mode(control$287);
4939 8 1 sum$x, sum$indexes, (sum$squares - 0) 0;
4941 /* Loop through array, accumulating sums */
4942 9 1 do i = 0 to n$of$x-1;
4943 10 2 sum$x = sum$x = x$array(i);
4944 11 2 sum$indexes = sum$indexes +
4945 (x$array(i) * float(i±1));
4946 12 2 sum$squares = sum$squares + (x$array(i)*x$array(i));
4953 PL/M-286 COMPILER ARRAYSUM
4954 CROSS-REFERENCE LISTING
4956 DEFN ADDR SIZE NAME,ATTRIBUTES, AND REFERENCES
4958 1 0006H 117 ARRAYSUM PROCEDURE STACK=002H
4959 5 CONTROL287 LITERALLY '033eh' 7
4961 4 019EH 2 I INTEGER 9* 9 10 11 12 13
4962 INITREALMATHUNIT BUILTIN 6
4963 4 019CH 2 NDFX INTEGER 9
4964 SETREALMODE BUILTIN 7
4965 2 0004H 4 SUMINDEXES REAL 8* 11 11*
4966 2 0008H 4 SUMSQAURES REAL 8* 12 12*
4967 2 0000H 4 SUMX REAL 8* 10 10*
4968 3 000CH 400 XARRAY REAL ARRAY(100) 10 11 12
4971 CODE AREA SIZE = 0077H 119D
4972 CONSTANT AREA SIZE = 0004H 4D
4973 VARIABLE AREA SIZE = 01A0H 416D
4974 MAXIMUM STACK SIZE = 0002H 2D
4980 96KB MEMORY AVILABLE
4981 3KB MEMORY USED (3%)
4984 END OF PL/M-286 COMPILATION
4987 Figure 2-7. Sample ASM286 Program
4989 iAPX286 MACRO ASSEMBLER EXAMPLE ASM286_PROGRAM
4991 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE EXAMPLE_ASM286_PROGRAM
4992 OBJECT MODULE PLACED IN :F6:287EXP.OBJ
4993 ASSEMBLER INVOKED BY ASM286 B6 :F6:287EXP.SRC XREF
4997 1 name example_ASM286_program
4998 2 ; Define intitialization routine
5001 5 ; Allocate space for date
5002 ---- 6 data segment rw public
5003 0000 3E03 7 control_287 dw 033eh
5004 0002 ???? 8 n_of_x dw ?
5005 0004 (000 9 x_array dd 100 dwp (?)
5008 0194 ???????? 10 sum_squares dd ?
5009 019B ???????? 11 sum_indexes dd ?
5010 019C ???????? 12 sum_x dd ?
5013 15 ; Allocate CPU stack space
5014 ---- 16 stack stackseg 400
5017 ---- 19 code segment or public
5018 20 assumes ds: data, ss: stack, es: nothing
5020 0000 BB---- R 22 mov ax,data
5021 0003 BED8 23 mov ds,ax
5022 0005 B8---- R 24 mov ax,stack
5023 0008 BED0 25 mov ss,ax
5024 000A BCFEFF R 26 mov sp,stackstart stack
5026 28 ; Assume x_array and n_of_x are initialized
5027 29 ; this pprogram zeroes n_of_x
5029 31 ; Prepare the 80287 or its emulator
5030 000D 9A0000---- E 32 call init287
5031 0012 D92E0000 R 33 fldcw control_287
5033 35 ; Clear three registers to hold running sums
5038 40 ; Setup CX as loop counter and
5039 41 ; SI as index to x_array
5040 001C 8B0E0200 R 42 mov cx,n_of_x
5041 0020 F7E9 43 imul cx
5042 0022 8BF0 44 mov si,ax
5044 46 ; SI now contains index of last element + 1
5045 47 ; Loop thru x_array, accumulating sums
5047 0024 8E3304 49 sub si,type x_array ;backup one element
5048 0027 D9840400 R 50 fld x_array[si] ;push it on the stack
5049 002B DCC3 51 fadd st(3),st ;add into sum of x
5050 002D D9C0 52 fld st ;duplicate x on tap
5051 002F DCC8 53 fmul st,st ;square it
5052 0031 DEC2 54 faddp st(2),st ;add into sum of (index+x)
5054 0033 FF0E0200 R 56 dec n_of_x ;reduce index for next iteration
5055 0037 E2EB 57 loop sum_next ;continue
5057 59 ; Pop running sums into memory
5058 0039 60 pop_results:
5059 0039 D91E9401 R 61 fstp sum_squares
5060 003D D91E9801 R 62 fstp sum_indexes
5061 0041 D91E9C01 R 63 fstp sum_x
5070 iAPX286 MACRO ASSEMBLER EXAMPLE_ASM286_PROGRAM
5071 XREF SYMBOL TABLE LISTING
5073 NAME TYPE VALUE ATTRIBUTES, XREFS
5075 CODE SEGMENT SIZE=0046H ER PUBLIC 19# 69
5076 CONTROL_287 V WORD 0000H DATA 7# 33
5077 DATA SEGMENT SIZE=01A0H RW PUBLIC 6# 13 20 22
5078 INIT287 L FAR 0000H EXTR 3# 32
5079 N_OF_X V WORD 0002H DATA 8# 42 56
5080 POP_RESULTS L NEAR 0039H CODE 60#
5081 STACK STACK SIZE=0190H RW PUBLIC 16# 20 24 26
5082 START L NEAR 0000H CODE 21# 70
5083 SUM_INDEXES V DWORD 0198H DATA 11# 62
5084 SUM_NEXT L NEAR 0024H CODE 48# 57
5085 SUM_SQUARES V DWORD 0194H DATA 10# 61
5086 SUM_X V DWORD 019CH DATA 12# 63
5087 X_ARAY V DWORD 0004H (100) DATA 9# 49 50
5089 END OF SYMBOL TABLE LISTING
5091 ASSEMBLY COMPLETE, NO ERRORS
5094 Figure 2-8. Instructions and Register Stack
5096 FLDZ,FLDZ,FLDZ FDL X_ARRAY[SI]
5097 ‚�����ƒ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
\x10‚�����ƒ
5098 ST(0)€ 0.0 € SUM_SQUARES ST(0)€ 2.5 € X_ARRAY(19)
5100 ST(1)€ 0.0 € SUM_INDEXES ST(1)€ € SUM_SQUARES
5102 ST(2)€ 0.0 € SUM_X ST(2)€ 0.0 € SUM_INDEXES
5105 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„�����…
5107 FADD ST(3),ST� FLD ST
5108 ‚�����ƒ
\x11‘•‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
\x10‚�����ƒ
5109 ST(0)€ 2.5 € X_ARRAY(19) ST(0)€ 2.5 € X_ARRAY(19)
5111 ST(1)€ 0.0 € SUM_SQUARES ST(1)€ 2.5 € X_ARRAY(19)
5113 ST(2)€ 0.0 € SUM_INDEXES ST(2)€ 0.0 € SUM_SQUARES
5115 ST(3)€ 2.5 € SUM_X ST(3)€ 0.0 € SUM_INDEXES
5118 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„�����…
5120 FMUL ST,ST� FADDP ST(2),ST
5121 ‚�����ƒ
\x11‘•‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
\x10‚�����ƒ
5122 ST(0)€ 6.25€ X_ARRAY(19)^(2) ST(0)€ 2.5 € X_ARRAY(19)
5124 ST(1)€ 2.5 € X_ARRAY(19) ST(1)€ 6.25€ SUM_SQUARES
5126 ST(2)€ 0.0 € SUM_SQUARES ST(2)€ 0.0 € SUM_INDEXES
5128 ST(3)€ 0.0 € SUM_INDEXES ST(3)€ 2.5 € SUM_X
5129 Ñ‘‘‘‘ ’‘‘‘‘‘‘‘‘‘‘‘„�����…
5130 ST(4)€ 2.5 € SUM_X �
5133 FIMUL N_OF_X� FADDP ST(2),ST
5134 ‚�����ƒ
\x11‘‘•‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
\x10‚�����ƒ
5135 ST(0)€ 50.0€ X_ARRAY(19)*20 ST(0)€ 6.25€ SUM_SQUARES
5137 ST(1)€ 6.25€ SUM_SQUARES ST(1)€ 50.0€ SUM_INDEXES
5139 ST(2)€ 0.0 € SUM_INDEXES ST(2)€ 2.5 € SUM_X
5146 The programming of applications to execute on both 80286 and 80287 is made
5147 much easier by the existence of an 80287 emulator for 80286 systems. The
5148 Intel E80287 emulator offers a complete software counterpart to the 80287
5149 hardware; NPX instructions can be simply emulated in software rather than
5150 being executed in hardware. With software emulation, the distinction
5151 between 80286 and 80287 systems is reduced to a simple performance
5152 differential (see Table 1-2 for a performance comparison between an actual
5153 80287 and an emulator 80287). Identical numeric programs will simply
5154 execute more slowly on 80286 systems (using software emulation of NPX
5155 instructions) than on executing NPX instructions directly.
5157 When incorporated into the systems software, the emulation of NPX
5158 instructions on the 80286 systems is completely transparent to the
5159 programmer. Applications software needs no special libraries, linking, or
5160 other activity to allow it to run on an 80286 with 80287 emulation.
5162 To the applications programmer, the development of programs for 80286
5163 systems is the same whether the 80287 NPX hardware is available or not. The
5164 full 80287 instruction set is available for use, with NPX instructions being
5165 either emulated or executed directly. Applications programmers need not be
5166 concerned with the hardware configuration of the computer systems on which
5167 their applications will eventually run.
5169 For systems programmers, details relating to 80287 emulators are described
5170 in a later section of this supplement. An E80287 software emulator for 80286
5171 systems is contained in the iMDX 364 8086 Software Toolbox, available from
5172 Intel and described in the 8086 Software Toolbox Manual.
5175 Concurrent Processing with the 80287
5176 Because the 80286 CPU and the 80287 NPX have separate execution units, it
5177 is possible for the NPX to execute numeric instructions in parallel with
5178 instructions executed by the CPU. This simultaneous execution of different
5179 instructions is called concurrency.
5181 No special programming techniques are required to gain the advantages of
5182 concurrent execution; numeric instructions for the NPX are simply placed in
5183 line with the instructions for the CPU. CPU and numeric instructions are
5184 initiated in the same order as they are encountered by the CPU in its
5185 instruction stream. However, because numeric operations performed by the NPX
5186 generally require more time than operations performed by the CPU, the CPU
5187 can often execute several of its instructions before the NPX completes a
5188 numeric instruction previously initiated.
5190 This concurrency offers obvious advantages in terms of execution
5191 performance, but concurrency also imposes several rules that must be
5192 observed in order to assure proper synchronization of the 80286 CPU and
5195 All Intel high-level languages automatically provide for and manage
5196 concurrency in the NPX. Assembly-language programmers, however, must
5197 understand and manage some areas of concurrency in exchange for the
5198 flexibility and performance of programming in assembly language. This
5199 section is for the assembly-language programmer or well-informed
5200 high-level-language programmer.
5203 Managing Concurrency
5204 Concurrent execution of the host and 80287 is easy to establish and
5205 maintain. The activities of numeric programs can be split into two major
5206 areas: program control and arithmetic. The program control part performs
5207 activities such as deciding what functions to perform, calculating
5208 addresses of numeric operands, and loop control. The arithmetic part simply
5209 adds, subtracts, multiplies, and performs other operations on the numeric
5210 operands. The NPX and host are designed to handle these two parts
5211 separately and efficiently.
5213 Managing concurrency is necessary because both the arithmetic and control
5214 areas must converge to a well-defined state before starting another numeric
5215 operation. A well-defined state means all previous arithmetic and control
5216 operations are complete and valid.
5218 Normally, the host waits for the 80287 to finish the current numeric
5219 operation before starting another. This waiting is called synchronization.
5221 Managing concurrent execution of the 80287 involves three types of
5224 1. Instruction synchronization
5225 2. Data synchronization
5226 3. Error synchronization
5228 For programmers in higher-level languages, all three types of
5229 synchronization are automatically provided by the appropriate compiler. For
5230 assembly-language programmers, instruction synchronization is guaranteed by
5231 the NPX interface, but data and error synchronization are the
5232 responsibility of the assembly-language programmer.
5235 Instruction Synchronization
5236 Instruction synchronization is required because the 80287 can perform only
5237 one numeric operation at a time. Before any numeric operation is started,
5238 the 80287 must have completed all activity from its previous instruction.
5240 Instruction synchronization is guaranteed for most ESC instructions because
5241 the 80286 automatically checks the BUSY status line from the 80287
5242 before commencing execution of most ESC instructions. No explicit WAIT
5243 instructions are necessary to ensure proper instruction synchronization.
5246 Data Synchronization
5247 Data synchronization addresses the issue of both the CPU and the NPX
5248 referencing the same memory values within a given block of code.
5249 Synchronization ensures that these two processors access the memory operands
5250 in the proper sequence, just as they would be accessed by a single
5251 processor with no concurrency. Data synchronization is not a concern when
5252 the CPU and NPX are using different memory operands during the course of one
5253 numeric instruction.
5255 The two cases where data synchronization might be a concern are
5257 1. The 80286 CPU reads or alters a memory operand first, then invokes
5258 the 80287 to load or alter the same operand.
5260 2. The 80287 is invoked to load or alter a memory operand, after which
5261 the 80286 CPU reads or alters the same location.
5263 Due to the instruction synchronization of the NPX interface, data
5264 synchronization is automatically provided for the first case‘‘the 80286 will
5265 always complete its operation before invoking the 80287.
5267 For the second case, data synchronization is not always automatic. In
5268 general, there is no guarantee that the 80287 will have finished its
5269 processing and accessed the memory operand before the 80286 accesses the
5272 Figure 2-9 shows examples of the two possible cases of the CPU and NPX
5273 sharing a memory value. In the examples of the first case, the CPU will
5274 finish with the operand before the 80287 can reference it. The NPX interface
5275 guarantees this. In the examples of the second case, the CPU must wait for
5276 the 80287 to finish with the memory operand before proceeding to reuse it.
5277 The FWAIT instructions shown in these examples are required in order to
5278 ensure this data synchronization.
5280 There are several NPX control instructions where automatic data
5281 synchronization is provided; however, the FSTSW/FNSTSW, FSTCW/FNSTCW, FLDCW,
5282 FRSTOR, and FLDENV instructions are all guaranteed to finish their execution
5283 before the CPU can read or alter the referenced memory locations.
5285 The 80287 provides data synchronization for these instructions by making a
5286 request on the Processor Extension Data Channel before the CPU executes its
5287 next instruction. Since the NPX data transfers occur before the CPU regains
5288 control of the local bus, the CPU cannot change a memory value before the
5289 NPX has had a chance to reference it. In the case of the FSTSW AX
5290 instruction, the 80286 AX register is explicitly updated before the CPU
5291 continues execution of the next instruction.
5293 For the numeric instructions not listed above, the assembly-language
5294 programmer must remain aware of synchronization and recognize cases
5295 requiring explicit data synchronization. Data synchronization can be
5296 provided either by programming an explicit FWAIT instruction, or by
5297 initiating a subsequent numeric instruction before accessing the operands or
5298 results of a previous instruction. After the subsequent numeric instruction
5299 has started execution, all memory references in earlier numeric
5300 instructions are complete. Reaching the next host instruction after the
5301 synchronizing numeric instruction indicates that previous numeric operands
5302 in memory are available.
5304 The data-synchronization function of any FWAIT or numeric instruction must
5305 be well-documented, as shown in figure 2-10. Otherwise, a change to the
5306 program at a later time may remove the synchronizing numeric instruction and
5307 cause program failure.
5309 High-level languages automatically establish data synchronization and
5310 manage it, but there may be applications where a high-level language may not
5313 For assembly-language programmers, automatic data synchronization can be
5314 obtained using the assembler, although concurrency of execution is lost as a
5315 result. To perform automatic data synchronization, the assembler can be
5316 changed to always place a WAIT instruction after the ESCAPE instruction.
5317 Figure 2-11 shows an example of how to change the ASM286 Code Macro for the
5318 FIST instruction to automatically place a WAIT instruction after the ESCAPE
5319 instruction. This Code Macro is included in the ASM286 source module. The
5320 price paid for this automatic data synchronization is the lack of any
5321 possible concurrency between the CPU and NPX.
5324 Figure 2-9. Synchronizing References to Shared Data
5336 Figure 2-10. Documenting Data Synchronization
5339 FMUL ; I is updated before FMUL is executed
5340 MOV AX, I ; I is now safe to use
5343 Figure 2-11. Nonconcurrent FIST Instruction Code Macro
5346 ; This is an ASM286 code macro to redefine the FIST
5347 ; instruction to prevent any concurrency
5348 ; while the instruction runs. A wait
5349 ; instruction is placed immediately after the
5350 ; escape to ensure the store is done
5351 ; before the program may continue.
5352 CodeMacro FIST memop: Mw
5359 Error Synchronization
5360 Almost any numeric instruction can, under the wrong circumstances, produce
5361 a numeric error. Concurrent execution of the CPU and NPX requires
5362 synchronization for these errors just as it does for data references and
5363 numeric instructions. In fact, the synchronization required for data and
5364 instructions automatically provides error synchronization.
5366 However, incorrect data or instruction synchronization may not be
5367 discovered until a numeric error occurs. A further complication is that a
5368 programmer may not expect his numeric program to cause numeric errors, but
5369 in some systems, they may regularly happen. To better understand these
5370 points, let's look at what can happen when the NPX detects an error.
5372 The NPX can perform one of two things when a numeric exception occurs:
5374 Ž The NPX can provide a default fix-up for selected numeric errors.
5375 Programs can mask individual error types to indicate that the NPX
5376 should generate a safe, reasonable result whenever that error occurs.
5377 The default error fix-up activity is treated by the NPX as part of the
5378 instruction causing the error; no external indication of the error is
5379 given. When errors are detected, a flag is set in the numeric status
5380 register, but no information regarding where or when is available. If
5381 the NPX performs its default action for all errors, then error
5382 synchronization is never exercised. This is no reason to ignore error
5383 synchronization, however.
5385 Ž As an alternative to the NPX default fix-up of numeric errors, the
5386 80286 CPU can be notified whenever an exception occurs. The CPU can
5387 then implement any sort of recovery procedures desired, for any numeric
5388 error detectable by the NPX. When a numeric error is unmasked and the
5389 error occurs, the NPX stops further execution of the numeric
5390 instruction and signals this event to the CPU. On the next occurrence
5391 of an ESC or WAIT instruction, the CPU traps to a software exception
5392 handler. Some ESC instructions do not check for errors. These are the
5393 nonwaited forms FNINIT, FNSTENV, FNSAVE, FNSTSW, FNSTCW, and FNCLEX.
5395 When the NPX signals an unmasked exception condition, it is requesting
5396 help. The fact that the error was unmasked indicates that further numeric
5397 program execution under the arithmetic and programming rules of the NPX is
5400 If concurrent execution is allowed, the state of the CPU when it recognizes
5401 the exception is undefined. The CPU may have changed many of its internal
5402 registers and be executing a totally different program by the time the
5403 exception occurs. To handle this situation, the NPX has special registers
5404 updated at the start of each numeric instruction to describe the state of
5405 the numeric program when the failed instruction was attempted.
5407 Error synchronization ensures that the NPX is in a well-defined state after
5408 an unmasked numeric error occurs. Without a well-defined state, it would be
5409 impossible for exception recovery routines to figure out why the numeric
5410 error occurred, or to recover successfully from the error.
5413 Incorrect Error Synchronization
5414 An example of how some instructions written without error synchronization
5415 will work initially, but fail when moved into a new environment is shown in
5418 In figure 2-12, three instructions are shown to load an integer, calculate
5419 its square root, then increment the integer. The NPX interface and
5420 synchronous execution of the NPX emulator will allow this program to execute
5421 correctly when no errors occur on the FILD instruction.
5423 This situation changes if the 80287 numeric register stack is extended to
5424 memory. To extend the NPX stack to memory, the invalid error is unmasked. A
5425 push to a full register or pop from an empty register will cause an invalid
5426 error. The recovery routine for the error must recognize this situation,
5427 fix up the stack, then perform the original operation.
5429 The recovery routine will not work correctly in the first example shown in
5430 the figure. The problem is that the value of COUNT is incremented before the
5431 NPX can signal the exception to the CPU. Because COUNT is incremented before
5432 the exception handler is invoked, the recovery routine will load an
5433 incorrect value of COUNT, causing the program to fail or behave unreliably.
5436 Figure 2-12. Error Synchronization Examples
5438 INCORRECT ERROR SYNCHRONIZATION
5440 FILD COUNT ; NPX instruction
5441 INC COUNT ; CPU instruction alters operand
5442 FSQRT COUNT ; subsequent NPX instruction -- error from
5443 ; previous NPX instruction detected here
5445 PROPER ERROR SYNCHRONIZATION
5447 FILD COUNT ; NPX instruction
5448 FSQRT COUNT ; subsequent NPX instruction - error from
5449 ; previous NPX instruction detected here
5450 INC COUNT ; CPU instruction alters operand
5453 Proper Error Synchronization
5454 Error Synchronization relies on the WAIT instructions required by
5455 instruction and data synchronization and the BUSY and ERROR signals of
5456 the 80287. When an unmasked error occurs in the 80287, it asserts the
5457 ERROR signal, signalling to the CPU that a numeric error has occurred.
5458 The next time the CPU encounters an error-checking ESC or WAIT instruction,
5459 the CPU acknowledges the ERROR signal by trapping automatically to
5460 Interrupt #16, the Processor Extension Error vector. If the following ESC
5461 or WAIT instruction is properly placed, the CPU will not yet have disturbed
5462 any information vital to recovery from the error.
5465 Chapter 3 System-Level Numeric Programming
5467 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
5469 System programming for 80287 systems requires a more detailed understanding
5470 of the 80287 NPX than does application programming. Such things as
5471 emulation, initialization, exception handling, and data and error
5472 synchronization are all the responsibility of the systems programmer. These
5473 topics are covered in detail in the sections that follow.
5477 On a software level, the 80287 NPX appears as an extension of the 80286
5478 CPU. On the hardware level, however, the mechanisms by which the 80286 and
5479 80287 interact are a bit more complex. This section describes how the 80287
5480 NPX and 80286 CPU interact and points out features of this interaction that
5481 are of interest to systems programmers.
5484 Processor Extension Data Channel
5485 All transfers of operands between the 80287 and system memory are performed
5486 by the 80286's internal Processor Extension Data Channel. This independent,
5487 DMA-like data channel permits all operand transfers of the 80287 to come
5488 under the supervision of the 80286 memory-management and protection
5489 mechanisms. The operation of this data channel is completely transparent to
5492 Because the 80286 actually performs all transfers between the 80287 and
5493 memory, no additional bus drivers, controllers, or other components are
5494 necessary to interface the 80287 NPX to the local bus. Any memory accessible
5495 to the 80286 CPU is accessible by the 80287. The Processor Extension Data
5496 Channel is described in more detail in Chapter Six of the 80286 Hardware
5500 Real-Address Mode and Protected Virtual-Address Mode
5501 Like the 80286 CPU, the 80287 NPX can operate in both Real-Address mode and
5502 in Protected mode. Following a hardware RESET, the 80287 is initially
5503 activated in Real-Address mode. A single, privileged instruction (FSETPM) is
5504 necessary to set the 80287 into Protected mode.
5506 As an extension to the 80286 CPU, the 80287 can access any memory location
5507 accessible by the task currently executing on the 80286. When operating in
5508 Protected mode, all memory references by the 80287 are automatically
5509 verified by the 80286's memory management and protection mechanisms as for
5510 any other memory references by the currently-executing task. Protection
5511 violations associated with NPX instructions automatically cause the 80286 to
5512 trap to an appropriate exception handler.
5514 To the programmer, these two 80287 operating modes differ only in the
5515 manner in which the NPX instruction and data pointers are represented in
5516 memory following an FSAVE or FSTENV instruction. When the 80287 operates in
5517 Protected mode, its NPX instruction and data pointers are each represented
5518 in memory as a 16-bit segment selector and a 16-bit offset. When the 80287
5519 operates in Real-Address mode, these same instruction and data pointers are
5520 represented simply as the 20-bit physical addresses of the operands in
5521 question (see figure 1-7 in Chapter One).
5524 Dedicated and Reserved I/O Locations
5525 The 80287 NPX does not require that any memory addresses be set aside for
5526 special purposes. The 80287 does make use of I/O port addresses in the range
5527 00F8H through 00FFH, although these I/O operations are completely
5528 transparent to the 80286 software. 80286 programs must not reference these
5529 reserved I/O addresses directly.
5531 To prevent any accidental misuse or other tampering with numeric
5532 instructions in the 80287, the 80286's I/O Privilege Level (IOPL) should be
5533 used in multiuser reprogrammable environments to restrict application
5534 program access to the I/O address space and so guarantee the integrity of
5535 80287 computations. Chapter Eight of the 80286 Operating System Writer's
5536 Guide contains more details regarding the use of the I/O Privilege Level.
5539 Processor Initialization and Control
5540 One of the principal responsibilities of systems software is the
5541 initialization, monitoring, and control of the hardware and software
5542 resources of the system, including the 80287 NPX. In this section, issues
5543 related to system initialization and control are described, including
5544 recognition of the NPX, emulation of the 80287 NPX in software if the
5545 hardware is not available, and the handling of exceptions that may occur
5546 during the execution of the 80287.
5549 System Initialization
5550 During initialization of an 80286 system, systems software must
5552 Ž Recognize the presence or absence of the NPX
5554 Ž Set flags in the 80286 MSW to reflect the state of the numeric
5557 If an 80287 NPX is present in the system, the NPX must be
5561 Ž Switched into Protected mode (if desired)
5563 All of these activities can be quickly and easily performed as part of the
5564 overall system initialization.
5567 Recognizing the 80287 NPX
5568 Figure 3-1 shows an example of a recognition routine that determines
5569 whether an NPX is present, and distinguishes between the 80387 and the
5570 8087/80287. This routine can be executed on any 80386, 80286, or 8086
5571 hardware configuration that has an NPX socket.
5573 The example guards against the possibility of accidentally reading an
5574 expected value from a floating data bus when no NPX is present. Data read
5575 from a floating bus is undefined. By expecting to read a specific bit
5576 pattern from the NPX, the routine protects itself from the indeterminate
5577 state of the bus. The example also avoids depending on any values in
5578 reserved bits, thereby maintaining compatibility with future numerics
5582 Figure 3-1. Software Routine to Recognize the 80287
5584 ; The following algorithm detects the presence of the 8087 as well as the
5585 ; 80287 in a system. This will make it easier for ISVs to port their 8086-87
5586 ; software to 286-287 systems.
5588 cc_cr equ 0DH ; carriage return
5589 cc_lf equ 0AH ; line feed
5591 assume cz:code, ds:data
5595 mov ax,data ; set data segment
5598 ; Test if 8087 is present in PC or PC/XT, or 80287 is in PC/AT
5600 fninit ; initialize coprocessor
5601 xor ah,ah ; zero ah register and memory byte
5602 mov byte ptr control + 1,ah
5603 fnstcw control ; store coprocessor's control word in
5605 mov ah,byte ptr control+1
5606 cmp ah,03h ; upper byte of control work will be
5607 ; 03 if 8087 or 80287 coprocessor
5612 mov ah,09h ; print string-coprocessor present
5613 mov dx,offset msg_yes
5619 mov ah,09h ; print string-coprocessor not
5621 mov dx,offset msg_no
5625 mov ah,4CH ; terminate program
5631 msg_yes db cc_cr,cc_lf,
5632 db 'System has an 8087 or 80287',cc_cr, cc_lf, '$'
5633 msg_no db cc_cr,cc_lf,
5634 db 'System does not have an 8087 or 80287',cc_cr, cc_lf,
5637 end start ; start is the entry point
5640 Configuring the Numerics Environment
5641 Once the 80286 CPU has determined the presence or absence of the 80287 NPX,
5642 the 80286 must set either the MP or the EM bit in its own machine status
5643 word accordingly. The initialization routine can either
5645 Ž Set the MP bit in the 80286 MSW to allow numeric instructions to be
5646 executed directly by the 80287 NPX component
5648 Ž Set the EM bit in the 80286 MSW to permit software emulation of the
5649 80287 numeric instructions
5651 The Math Present (MP) flag of the 80286 machine status word indicates to
5652 the CPU whether an 80287 NPX is physically available in the system. The MP
5653 flag controls the function of the WAIT instruction. When executing a WAIT
5654 instruction, the 80286 tests only the Task Switched (TS) bit if MP is set;
5655 if it finds TS set under these conditions, the CPU traps to exception #7.
5657 The Emulation Mode (EM) bit of the 80286 machine status word indicates to
5658 the CPU whether NPX functions are to be emulated. If the CPU finds EM set
5659 when it executes an ESC instruction, program control is automatically
5660 trapped to exception #7, giving the exception handler the opportunity to
5661 emulate the functions of an 80287. The 80286 EM flag can be changed only by
5662 using the LMSW (load machine status word) instruction (legal only at
5663 privilege level 0) and examined with the aid of the SMSW (store machine
5664 status word) instruction (legal at any privilege level).
5666 The EM bit also controls the function of the WAIT instruction. If the CPU
5667 finds EM set while executing a WAIT, the CPU does not check the ERROR
5668 pin for an error indication.
5670 For correct 80286 operation, the EM bit must never be set concurrently with
5671 MP. The EM and MP bits of the 80286 are described in more detail in the
5672 80286 Operating System Writer's Guide. More information on software
5673 emulation for the 80287 NPX is described in the "80287 Emulation" section
5674 later in this chapter.
5676 In any case, if ESC instructions are to be executed, either the MP or EM
5677 bit must be set, but not both.
5680 Initializing the 80287
5681 Initializing the 80287 NPX simply means placing the NPX in a known state
5682 unaffected by any activity performed earlier. The example software routine
5683 to recognize the 80287 (figure 3-1) performed this initialization using a
5684 single FNINIT instruction. This instruction causes the NPX to be
5685 initialized in the same way as that caused by the hardware RESET signal to
5686 the 80287. All the error masks are set, all registers are tagged empty, the
5687 ST is set to zero, and default rounding, precision, and infinity controls
5688 are set. Table 3-1 shows the state of the 80287 NPX following
5691 Following a hardware RESET signal, such as after initial power-up, the
5692 80287 is initialized in Real-Address mode. Once the 80287 has been switched
5693 to Protected mode (using the FSETPM instruction), only another hardware
5694 RESET can switch the 80287 back to Real-Address mode. The FNINIT instruction
5695 does not switch the operating state of the 80287.
5699 If it is determined that no 80287 NPX is available in the system, systems
5700 software may decide to emulate ESC instructions in software. This emulation
5701 is easily supported by the 80286 hardware, because the 80286 can be
5702 configured to trap to a software emulation routine whenever it encounters
5703 an ESC instruction in its instruction stream.
5705 As described previously, whenever the 80286 CPU encounters an ESC
5706 instruction, and its MP and EM status bits are set appropriately (MP = 0,
5707 EM = 1), the 80286 will automatically trap to interrupt #7, the Processor
5708 Extension Not Available exception. The return link stored on the stack
5709 points to the first byte of the ESC instruction, including the prefix
5710 byte(s), if any. The exception handler can use this return link to examine
5711 the ESC instruction and proceed to emulate the numeric instruction in
5714 The emulator must step the return pointer so that, upon return from the
5715 exception handler, execution can resume at the first instruction following
5716 the ESC instruction.
5718 To an application program, execution on an 80286 system with 80287
5719 emulation is almost indistinguishable from execution on an 80287 system,
5720 except for the difference in execution speeds.
5722 There are several important considerations when using emulation on an 80286
5725 Ž When operating in Protected-Address mode, numeric applications using
5726 the emulator must be executed in execute-readable code segments.
5727 Numeric software cannot be emulated if it is executed in execute-only
5728 code segments. This is because the emulator must be able to examine
5729 the particular numeric instruction that caused the Emulation trap.
5731 Ž Only privileged tasks can place the 80286 in emulation mode. The
5732 instructions necessary to place the 80286 in Emulation mode are
5733 privileged instructions, and are not typically accessible to an
5736 An emulator package (E80287) that runs on 80286 systems is available from
5737 Intel in the 8086 Software Toolbox, Order Number 122203. This emulation
5738 package operates in both Real and Protected mode, providing a complete
5739 functional equivalent for the 80287 emulated in software.
5741 When using the E80287 emulator, writers of numeric exception handlers
5742 should be aware of one slight difference between the emulated 80287 and the
5745 Ž On the 80287 hardware, exception handlers are invoked by the 80286 at
5746 the first WAIT or ESC instruction following the instruction causing the
5747 exception. The return link, stored on the 80286 stack, points to this
5748 second WAIT or ESC instruction where execution will resume following a
5749 return from the exception handler.
5751 Ž Using the E80287 emulator, numeric exception handlers are invoked from
5752 within the emulator itself. The return link stored on the stack when
5753 the exception handler is invoked will therefore point back to the
5754 E80287 emulator, rather than to the program code actually being
5755 executed (emulated). An IRET return from the exception handler returns
5756 to the emulator, which then returns immediately to the emulated
5757 program. This added layer of indirection should not cause confusion,
5758 however, because the instruction causing the exception can always be
5759 identified from the 80287's instruction and data pointers.
5762 Table 3-1. NPX Processor State Following Initialization
5765 Field Value Interpretation
5768 Infinity Control 0 Projective
5769 Rounding Control 00 Round to nearest
5770 Precision Control 11 64 bits
5771 Interrupt-Enable Mask 1 Interrupts disabled
5772 Exception Masks 111111 All exceptions masked
5776 Condition Code ???? (Indeterminate)
5777 Stack Top 000 Empty stack
5778 Interrupt Request 0 No interrupt
5779 Exception Flags 000000 No exceptions
5784 Registers N.C. Not changed
5787 Instruction Code N.C. Not changed
5788 Instruction Address N.C. Not changed
5789 Operand Address N.C. Not changed
5792 Handling Numeric Processing Exceptions
5793 Once the 80287 has been initialized and normal execution of applications
5794 has been commenced, the 80287 NPX may occasionally require attention in
5795 order to recover from numeric processing errors. This section provides
5796 details for writing software exception handlers for numeric exceptions.
5797 Numeric processing exceptions have already been introduced in previous
5798 sections of this manual.
5800 As discussed previously, the 80287 NPX can take one of two actions when it
5801 recognizes a numeric exception:
5803 Ž If the exception is masked, the NPX will automatically perform its own
5804 masked exception response, correcting the exception condition according
5805 to fixed rules, and then continuing with its instruction execution.
5807 Ž If the exception is unmasked, the NPX signals the exception to the
5808 80286 CPU using the ERROR status line between the two processors.
5809 Each time the 80286 encounters an ESC or WAIT instruction in its
5810 instruction stream, the CPU checks the condition of this ERROR
5811 status line. If ERROR is active, the CPU automatically traps to
5812 Interrupt vector #16, the Processor Extension Error trap.
5814 Interrupt vector #16 typically points to a software exception handler,
5815 which may or may not be a part of systems software. This exception handler
5816 takes the form of an 80286 interrupt procedure.
5818 When handling numeric errors, the CPU has two responsibilities:
5820 Ž The CPU must not disturb the numeric context when an error is
5823 Ž The CPU must clear the error and attempt recovery from the error.
5825 Although the manner in which programmers may treat these responsibilities
5826 varies from one implementation to the next, most exception handlers will
5827 include these basic steps:
5829 Ž Store the NPX environment (control, status, and tag words, operand and
5830 instruction pointers) as it existed at the time of the exception.
5832 Ž Clear the exception bits in the status word.
5834 Ž Enable interrupts on the CPU.
5836 Ž Identify the exception by examining the status and control words in
5837 the save environment.
5839 Ž Take some system-dependent action to rectify the exception.
5841 Ž Return to the interrupted program and resume normal execution.
5843 It should be noted that the NPX exception pointers contained in the stored
5844 NPX environment will take different forms, depending on whether the NPX is
5845 operating in Real-Address mode or in Protected mode. The earlier discussion
5846 of Real versus Protected mode details how this information is presented in
5847 each of the two operating modes.
5850 Simultaneous Exception Response
5851 In cases where multiple exceptions arise simultaneously, the 80287 signals
5852 one exception according to the precedence sequence shown in table 3-2. This
5853 means, for example, that zero divided by zero will result in an invalid
5854 operation, and not a zero divide exception.
5857 Exception Recovery Examples
5858 Recovery routines for NPX exceptions can take a variety of forms. They can
5859 change the arithmetic and programming rules of the NPX. These changes may
5860 redefine the default fix-up for an error, change the appearance of the NPX
5861 to the programmer, or change how arithmetic is defined on the NPX.
5863 A change to an error response might be to automatically normalize all
5864 denormals loaded from memory. A change in appearance might be extending the
5865 register stack into memory to provide an "infinite" number of numeric
5866 registers. The arithmetic of the NPX can be changed to automatically extend
5867 the precision and range of variables when exceeded. All these functions can
5868 be implemented on the NPX via numeric errors and associated recovery
5869 routines in a manner transparent to the application programmer.
5871 Some other possible system-dependent actions, mentioned previously, may
5874 Ž Incrementing an exception counter for later display or printing
5876 Ž Printing or displaying diagnostic information (e.g., the 80287
5877 environment and registers)
5879 Ž Aborting further execution
5881 Ž Storing a diagnostic value (a NaN) in the result and continuing with
5884 Notice that an exception may or may not constitute an error, depending on
5885 the implementation. Once the exception handler corrects the error condition
5886 causing the exception, the floating-point instruction that caused the
5887 exception can be restarted, if appropriate. This cannot be accomplished
5888 using the IRET instruction, however, because the trap occurs at the ESC or
5889 WAIT instruction following the offending ESC instruction. The exception
5890 handler must obtain from the NPX the address of the offending instruction in
5891 the task that initiated it, make a copy of it, execute the copy in the
5892 context of the offending task, and then return via IRET to the current CPU
5895 In order to correct the condition causing the numeric exception, exception
5896 handlers must recognize the precise state of the NPX at the time the
5897 exception handler was invoked, and be able to reconstruct the state of the
5898 NPX when the exception initially occurred. To reconstruct the state of the
5899 NPX, programmers must understand when, during the execution of an NPX
5900 instruction, exceptions are actually recognized.
5902 Invalid operation, zero divide, and denormalized exceptions are detected
5903 before an operation begins, whereas overflow, underflow, and precision
5904 exceptions are not raised until a true result has been computed. When a
5905 before exception is detected, the NPX register stack and memory have
5906 not yet been updated, and appear as if the offending instructions has not
5909 When an after exception is detected, the register stack and memory appear
5910 as if the instruction has run to completion; i.e., they may be updated.
5911 (However, in a store or store-and-pop operation, unmasked over/underflow is
5912 handled like a before exception; memory is not updated and the stack is not
5913 popped.) The programming examples contained in Chapter Four include an
5914 outline of several exception handlers to process numeric exceptions for the
5918 Table 3-2. Precedence of NPX Exceptions
5920 Signaled First: Denormalized operand (if unmasked)
5923 Denormalized (if masked)
5925 Signaled Last: Precision
5928 Chapter 4 Numeric Programming Examples
5930 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
5932 The following sections contain examples of numeric programs for the 80287
5933 NPX written in ASM286. These examples are intended to illustrate some of the
5934 techniques for programming the 80287 computing system for numeric
5938 Conditional Branching Examples
5939 As discussed in Chapter Two, several numeric instructions post their
5940 results to the condition code bits of the 80287 status word. Although there
5941 are many ways to implement conditional branching following a comparison, the
5942 basic approach is as follows:
5944 Ž Execute the comparison.
5946 Ž Store the status word. (80287 allows storing status directly into AX
5949 Ž Inspect the condition code bits.
5951 Ž Jump on the result.
5953 Figure 4-1 is a code fragment that illustrates how two memory-resident long
5954 real numbers might be compared (similar code could be used with the FTST
5955 instruction). The numbers are called A and B, and the comparison is A to B.
5957 The comparison itself requires loading A onto the top of the 80287 register
5958 stack and then comparing it to B, while popping the stack with the same
5959 instruction. The status word is then written into the 80286 AX register.
5961 A and B have four possible orderings, and bits C3, C2, and C0 of the
5962 condition code indicate which ordering holds. These bits are positioned in
5963 the upper byte of the NPX status word so as to correspond to the CPU's zero,
5964 parity, and carry flags (ZF, PF, and CF), when the byte is written into the
5965 flags. The code fragment sets ZF, PF, and CF of the CPU status word to the
5966 values of C3, C2, and C0 of the NPX status word, and then uses the CPU
5967 conditional jump instructions to test the flags. The resulting code is
5968 extremely compact, requiring only seven instructions.
5970 The FXAM instruction updates all four condition code bits. Figure 4-2 shows
5971 how a jump table can be used to determine the characteristics of the value
5972 examined. The jump table (FXAM_TBL) is initialized to contain the 16-bit
5973 displacement of 16 labels, one for each possible condition code setting.
5974 Note that four of the table entries contain the same value, because four
5975 condition code settings correspond to "empty."
5977 The program fragment performs the FXAM and stores the status word. It then
5978 manipulates the condition code bits to finally produce a number in register
5979 BX that equals the condition code times 2. This involves zeroing the unused
5980 bits in the byte that contains the code, shifting C3 to the right so that
5981 it is adjacent to C2, and then shifting the code to multiply it by 2. The
5982 resulting value is used as an index that selects one of the displacements
5983 from FXAM_TBL (the multiplication of the condition code is required because
5984 of the 2-byte length of each value in FXAM_TBL). The unconditional JMP
5985 instruction effectively vectors through the jump table to the labelled
5986 routine that contains code (not shown in the example) to process each
5987 possible result of the FXAM instruction.
5990 Figure 4-1. Conditional Branching for Compares
6000 FLD A ; LOAD A ONTO TOP OF 287 STACK
6001 FCOMP B ; COMPARE A:B, POP A
6002 FSTSW AX ; STORE RESULT TO CPU AX REGISTER
6004 ; CPU AX REGISTER CONTAINS CONDITION CODES (RESULTS OF
6006 ; LOAD CONDITION CODES INTO CPU FLAGS
6009 ; USE CONDITIONAL JUMPS TO DETERMINE ORDERING OF A TO B
6011 JP A_B_UNORDERED ; TEST C2 (PF)
6012 JB A_LESS ; TEST C0 (CF)
6013 JE A_EQUAL ; TEST C3 (ZF)
6014 A_GREATER: ; C0 (CF) = 0, C3 (ZF) = 0
6017 A_EQUAL: ; C0 (CF) = 0, C3 (ZF) = 1
6020 A_LESS: ; C0 (CF) = 1, C3 (ZF) = 0
6023 A_B_UNORDERED: ; C2 (PF) = 1
6028 Figure 4-2. Conditional Branching for FXAM
6030 ; JUMP TABLE FOR EXAMINE ROUTINE
6032 FXAM_TBL DW POS_UNNORM, POS_NAN, NEG_UNNORM, NEG_NAN,
6033 & POS_NORM, POS_INFINITY, NEG_NORM,
6034 & NEG_INFINITY, POS_ZERO, EMPTY, NEG_ZERO,
6035 & EMPTY, POS_DENORM, EMPTY, NEG_DENORM, EMPTY
6038 ; EXAMINE ST AND STORE RESULT (CONDITION CODES)
6042 ; CALCULATE OFFSET INTO JUMP TABLE
6043 MOV BH,0 ; CLEAR UPPER HALF OF BX,
6044 MOV BL,AH ; LOAD CONDITION CODE INTO BL
6045 AND BL,00000111B ; CLEAR ALL BITS EXCEPT C2-C0
6046 AND AH,01000000B ; CLEAR ALL BITS EXCEPT C3
6047 SHR AH,2 ; SHIFT C3 TWO PLACES RIGHT
6048 SAL BX,1 ; SHIFT C2-C0 1 PLACE LEFT (MULTIPLY
6050 OR BL,AH ; DROP C3 BACK IN ADJACENT TO C2
6053 ; JUMP TO THE ROUTINE `ADDRESSED' BY CONDITION CODE
6056 ; HERE ARE THE JUMP TARGETS, ONE TO HANDLE
6057 ; EACH POSSIBLE RESULT OF FXAM
6085 Exception Handling Examples
6086 There are many approaches to writing exception handlers. One useful
6087 technique is to consider the exception handler procedure as consisting of
6088 "prologue," "body," and "epilogue" sections of code. (For compatibility with
6089 the 80287 emulators, this procedure should be invoked by interrupt pointer
6090 (vector) number 16.)
6092 At the beginning of the prologue, CPU interrupts have been disabled. The
6093 prologue performs all functions that must be protected from possible
6094 interruption by higher-priority sources. Typically, this will involve saving
6095 CPU registers and transferring diagnostic information from the 80287 to
6096 memory. When the critical processing has been completed, the prologue may
6097 enable CPU interrupts to allow higher-priority interrupt handlers to preempt
6098 the exception handler.
6100 The exception handler body examines the diagnostic information and makes a
6101 response that is necessarily application-dependent. This response may range
6102 from halting execution, to displaying a message, to attempting to repair the
6103 problem and proceed with normal execution.
6105 The epilogue essentially reverses the actions of the prologue, restoring
6106 the CPU and the NPX so that normal execution can be resumed. The epilogue
6107 must not load an unmasked exception flag into the 80287 or another exception
6108 will be requested immediately.
6110 Figures 4-3, 4-4 and 4-5 show the ASM286 coding of three skeleton
6111 exception handlers. They show how prologues and epilogues can be written for
6112 various situations, but provide comments indicating only where the
6113 application-dependent exception handling body should be placed.
6115 Figure 4-3 and 4-4 are very similar; their only substantial difference is
6116 their choice of instructions to save and restore the 80287. The tradeoff
6117 here is between the increased diagnostic information provided by FNSAVE and
6118 the faster execution of FNSTENV. For applications that are sensitive to
6119 interrupt latency or that do not need to examine register contents, FNSTENV
6120 reduces the duration of the "critical region," during which the CPU will
6121 not recognize another interrupt request (unless it is a nonmaskable
6124 After the exception handler body, the epilogues prepare the CPU and the NPX
6125 to resume execution from the point of interruption (i.e., the instruction
6126 following the one that generated the unmasked exception). Notice that the
6127 exception flags in the memory image that is loaded into the 80287 are
6128 cleared to zero prior to reloading (in fact, in these examples, the entire
6129 status word image is cleared).
6131 The examples in figures 4-3 and 4-4 assume that the exception handler
6132 itself will not cause an unmasked exception. Where this is a possibility,
6133 the general approach shown in figure 4-5 can be employed. The basic
6134 technique is to save the full 80287 state and then to load a new control
6135 word in the prologue. Note that considerable care should be taken when
6136 designing an exception handler of this type to prevent the handler from
6137 being reentered endlessly.
6140 Figure 4-3. Full-State Exception Handler
6144 ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 STATE IMAGE
6148 ; SAVE FULL 80287 STATE, WAIT FOR COMPLETION, ENABLE CPU INTERRUPTS
6153 ; APPLICATION-DEPENDENT EXCEPTION HANDLING CODE GOES HERE
6155 ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED STATE IMAGE
6156 MOV BYTE PTR [BP-92], 0H
6158 ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
6164 ; RETURN TO INTERRUPTED CALCULATION
6169 Figure 4-4. Reduced-Latency Exception Handler
6171 SAVE_ENVIRONMENT PROC
6173 ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 ENVIRONMENT
6178 ; SAVE ENVIRONMENT, WAIT FOR COMPLETION, ENABLE CPU INTERRUPTS
6183 ; APPLICATION EXCEPTION-HANDLING CODE GOES HERE
6185 ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED
6187 MOV BYTE PTR [BP-12], 0H
6189 ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
6193 ; RETURN TO INTERRUPTED CALCULATION
6195 SAVE_ENVIRONMENT ENDP
6198 Figure 4-5. Reentrant Exception Handler
6203 LOCAL_CONTROL DW ? ; ASSUME INITIALIZED
6209 ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR
6217 ; SAVE STATE, LOAD NEW CONTROL WORD, FOR COMPLETION, ENABLE CPU
6225 ; APPLICATION EXCEPTION HANDLING CODE GOES HERE.
6226 ; AN UNMASKED EXCEPTION GENERATED HERE WILL CAUSE THE EXCEPTION
6227 ; HANDLER TO BE REENTERED.
6228 ; IF LOCAL STORAGE IS NEEDED, IT MUST BE ALLOCATED ON THE CPU STACK.
6232 ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED STATE IMAGE
6233 MOV BYTE PTR [BP-92], 0H
6235 ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
6241 ; RETURN TO POINT OF INTERRUPTION
6246 Floating-Point to ASCII Conversion Examples
6247 Numeric programs must typically format their results at some point for
6248 presentation and inspection by the program user. In many cases, numeric
6249 results are formatted as ASCII strings for printing or display. This example
6250 shows how floating-point values can be converted to decimal ASCII character
6251 strings. The function shown in figure 4-6 can be invoked from PL/M-286,
6252 Pascal-286, FORTRAN-286, or ASM286 routines.
6254 Shortness, speed, and accuracy were chosen rather than providing the
6255 maximum number of significant digits possible. An attempt is made to keep
6256 integers in their own domain to avoid unnecessary conversion errors.
6258 Using the extended precision real number format, this routine achieves a
6259 worst case accuracy of three units in the 16th decimal position for a
6260 noninteger value or integers greater than 10^(18). This is double precision
6261 accuracy. With values having decimal exponents less than 100 in magnitude,
6262 the accuracy is one unit in the 17th decimal position.
6264 Higher precision can be achieved with greater care in programming, larger
6265 program size, and lower performance.
6268 Figure 4-6. Floating-Point to ASCII Conversion Routine
6270 iAPX286 MACRO ASSEMBLER 80287 Floating-Point to 18-Digit ASCII Conversion 10:12:38 09/25/83 PAGE 1
6272 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE FLOATING_TO_ASCII
6273 OBJECT MODULE PLACED IN :F3:FPASC.OBJ
6274 ASSEMBLER INVOKED BY: ASM286.86 :F3:FPASC.AP2
6278 1 +1 $title("80287 Floating-Point to 18-Digit ASCII Conversion")
6280 3 name floating_to_ascii
6282 5 public floating_to_ascii
6283 6 extrn get_power_IO near.tos_status near
6285 8 ; This subroutine will convert the floating point number in the
6286 9 ; top of the 80287 stack to an ASCII string and separate power of 10
6287 10 ; scaling value (in binary). The maximum width of the ASCII string
6288 11 ; formed is controlled by a parameter which must be > 1. Unnormal values,
6289 12 ; denormal values, and psuedo zeroes will be correclty converted.
6290 13 ; A returned value will indicate how many binary bits of
6291 14 ; precision were lost in an unnormal or denormal value. The magnitude
6292 15 ; (in terms of binary power) of a psuedo zero will also be indicated.
6293 16 ; Integers less than 10**18 in magnitude are accurately converted if the
6294 17 ; destination ASCII string field is wide enough to hold all the
6295 18 ; digits. Otherwise the value is converted to scientific notation.
6297 20 ; The status of the conversion is identified by the return value,
6300 23 ; 0 conversion complete, string_size is defined
6301 24 ; 1 invalid arguments
6302 25 ; 2 exact integer conversion, string_size is defined
6304 27 ; 4 + NAN (Not A Number)
6308 31 ; 8 psuedo zero found, string_size is defined
6310 33 ; The PLM/286 calling convention is
6312 35 ;floating_to_ascii:
6313 36 ; procedure (number,denormal ptr, string ptr, size_ptr, field_size,
6314 37 ; power_ptr) word external.
6315 38 ; declare (denormal_ptr, string ptr, power ptr, size_ptr) pointer,
6316 39 ; declare field_size word, string_size basd size_ptr word,
6317 40 ; delcare number real;
6318 41 ; declare denormal integer based denormal_ptr,
6319 42 ; declare power integer based power_ptr,
6320 43 ; and floating_to_ascii,
6322 45 ; The floating point value is expected to be on the top of the NPX
6323 46 ; stack. This subroutine expects 3 free entries on the NPX stack and
6324 47 ; will pop the passed value off when done. The generated ASCII string
6325 48 ; will have a leading character either '-' or '+' indicating the sign
6326 49 ; of the value. The ASCII decimal digits will immediately follow.
6327 50 ; The numeric value of the ASCII string is (ASCII STRING )*10**POWER.
6328 51 ; If the given number was zero, the ASCII string will contain a sign
6329 52 ; and a single zero character. The value string_size indicates the total
6330 53 ; length of the ASCII string including the sign character. String(0) will
6331 54 ; always hold the sign. It is possible for string_size to be less than
6332 55 ; field_size. This occurs for zeroes or integer values. A psuedo zero
6333 56 ; will return a special return code. The denormal count will indicate
6334 57 ; the power of the two originally associated with the value. The power of
6335 58 ; ten and ASCII string will be as if the value was an ordinary zero.
6337 60 ; The subroutine is accurate up to a maximum of 18 decimal digits for
6338 61 ; integers. Integer values will have a decimal power of zero associated
6339 62 ; with them. For non-integers, the result will be accurate to within 2
6340 63 ; decimal digits of the 16th decimal place (double pracision). The
6341 64 ; exponentiate instruction is also used for scaling the value into the
6342 65 ; range acceptable for the BCD data type. The rounding mode in effect
6343 66 ; on entry to the subroutine is used for the conversion.
6345 68 ; The following registers are not tranparent
6347 70 ; ax bx cx dx si di flags
6351 74 ; Define the stack layout
6353 0000[] 76 bp_save equ word ptr [bp]
6354 0002[] 77 es_save equ bp_save + size bp_save
6355 0004[] 78 return_ptr equ es_save + size es_save
6356 0006[] 79 power_ptr equ return_ptr _ size return_ptr
6357 0008[] 80 field_size equ power_ptr + size power_ptr
6358 000A[] 81 size_ptr equ field_size + size field_size
6359 000C[] 82 string_ptr equ size_ptr + size size_ptr
6360 000E[] 83 denormal_ptr equ string_ptr + size string_ptr
6362 85 parms_size equ size power_ptr + size field_size + size_ptr +
6363 000A 86 & size string_ptr + size denormal_ptr
6365 88 Define constants used
6367 0012 90 BCD_DIGIIS equ 18 ; Number of digits in bcd_value
6368 0002 91 WORD-SIZE equ 2
6369 000A 92 BCD_SIZE equ 10
6370 0001 93 MINUS equ 1 ; Define return values
6371 0004 94 NAN equ 4 ; The exact values chosen here are
6372 0006 95 INFINITY equ 6 ; important. They must correspond to
6373 0003 96 INDEFINITE equ 3 ; the possible return values and be in
6374 0008 97 PSUEDO_ZERO equ 8 ; the same numeric order as tested by
6375 -0002 98 INVALID equ -2 ; the program.
6376 -0004 99 ZERO equ -4
6377 -0006 100 DENORMAL equ -6
6378 0008 101 UNNORMAL equ -8
6379 0000 102 NORMAL equ 0
6380 0002 103 EXACT equ 2
6382 105 ; Define layout of temporary storage area
6384 -0002[] 107 status equ word ptr [bp-WORD_SIZE]
6385 -0004[] 108 power_two equ status - WORD_SIZE
6386 -0006[] 109 power_ten equ power_two - WORD_SIZE
6387 -0010[] 110 bcd_value equ tbyte ptr power_ten - BCD_SIZE
6388 -0010[] 111 bcd_byte equ byte ptr bcd_value
6389 -0010[] 112 fraction equ bcd_value
6391 114 local_size equ size status + size pwer_two + size power_ten
6392 0010 115 & + size bcd_value
6394 ---- 117 stack stackseg (local_size+6) ; Allocate stack space for locals
6396 ---- 119 code segment or public
6397 120 extrn power_table:qword
6399 122 ; Constants used by this function
6401 124 even ; Optimize for 16 bits
6402 0000 0A00 125 const10 dw 10 ; Adjustment value for too big BCD
6404 127 ; Convert the C3,C2,C1,C0 encoding from tos_status into meaningful bit
6405 128 ; flags and values.
6407 0002 F8 130 status_table db UNNORMAL, NAN, UNNORMAL + MINUS, NAN + MINUS
6411 0006 00 131 & NORMAL, INFINITY, NORMAL + MINUS, INFINITY + MINUS
6415 000A FC 132 & ZERO, INVALID, ZERO + MINUS, INVALID
6419 000E FA 133 & DENORMAL, INVALID, DENORMAL + MINUS, INVALID
6424 0012 135 floating_to_ascii proc
6426 0012 E80000 137 call tos_status ; look at status of ST(0)
6427 0015 8BD8 138 mov bx,ax ; Get descriptor from table
6428 0017 2E8A870200 139 mov al,status_table[bx]
6429 001C 3CFE 140 cmp al,INVALID ; Look for empty ST(0)
6430 001E 752B 141 jne not_empty
6432 143 ; ST(0) is empty! Return the status value
6434 0020 C20A00 145 ret parms_size
6436 147 ; Remove infinity from stack and exit
6438 0023 149 found_infinity
6440 0023 DDD8 151 fstp st(0) ; OR to leave fstp running
6441 0025 EB02 152 jmp short exit_proc
6443 154 ; String space is too small! Return invalid code
6445 0027 156 small_string
6447 0027 B0FE 158 mov al,INVALID
6451 0029 C9 162 leave ; Restore stack
6453 002B C20A00 164 ret parms_size
6455 166 ; ST(0) is NAN or indefinite. Store the value in memory and look
6456 167 ; at the fraction field to separate indefinite from an ordinary NAN.
6458 002E 169 NAN_or_indefinite:
6460 0031 A801 171 fstp fraction ; Remove value from stack for examination
6461 0033 9B 172 test al,MINUS ; Look at sign bit
6462 0034 74F3 173 fwait ; Insure store is done
6463 174 jz exit_proc ; Can't be indefinite if positive
6465 0039 2B5EF6 176 mov bx,0C000H ; Match against upper 16 bits of fraction
6466 003C 0B5EF4 177 sub bx,word ptr fraction+6 ; Compare bits 63-4B
6467 003F 0B5EF2 178 or bx,word ptr fraction+4 ; Bits 32-47 must be zero
6468 0042 0B5EF0 179 or bx,word ptr fraction+2 ; Bits 31-16 must be zero
6469 0045 75E2 180 or bx,word ptr fraction ; Bits 15-0 must be zero
6472 0049 EBDE 183 mov al,INDEFINITE ; Set return value for indefinite value
6475 186 ; Allocate stack space for local variables and establish parameter
6476 187 ; addressibility.
6480 004B 06 191 push es ; Save working register
6481 004C C8100000 192 enter local_size,0 ; Format stack
6483 0050 8B4E08 194 mov cx,field_ize ; Check for enough string space
6484 0053 83F902 195 cmp cx,2
6485 0056 7CCF 196 jl sjall_string
6487 005B 49 198 dec cx ; Adjust for sign character
6488 0059 83F912 199 cmp cx,BCD_DIGITS ; See if string is too large for BCD
6489 005C 7603 200 jbe size_ok
6491 005E B91200 202 mov cx,BCD_DIGITS ; Else set maximum string size
6495 0061 3C06 206 cmp al,INFINITY ; Look for infinity
6496 0063 7DBE 207 jge found_infinity ; Return status value for + or - inf
6498 0065 3C04 209 cmp al,NAN ; Look for NAN or INDEFINITE
6499 0067 7DC5 210 jge NAN_or_indefinite
6501 212 ; Set default return values and check that the number is normalized
6503 0069 D9E1 214 fabs ; Use positive value only
6504 215 ; sign bit in al has true sign of value
6505 006B 8BD0 216 mov dx,ax ; Save return value for later
6506 006D 33C0 217 xor ax,ax ; Form 0 constant
6507 006F 8B7E0E 218 mov di,denormal_ptr ; Zero denormal count
6508 0072 8905 219 mov word ptr [di],ax
6509 0074 8B5E06 220 mov bx,power_ptr ; Zero power of ten value
6510 0077 B907 221 mov word ptr [bx],ax
6511 0079 80FAFC 222 cmp dl,ZERO ; Test for zero
6512 007C 732B 223 jae real_zero ; Skip power code if value is zero
6514 007E 80FAFA 225 cmp dl,DENORMAL ; Look for a denormal value
6515 008A 732C 226 jae found_denormal ; Handle it specially
6517 0083 D9F4 228 fxtract ; Separate exponent from signifand
6518 0085 80FAF8 229 cmp dl,UNNORMAL ; Test for unnormal value
6519 0088 7240 230 jb normal_value
6521 008A 80EAF8 232 sub dl,UNNORMAL-NORMAL ; Return normal status with correct sign
6523 234 ; Normalize the fraction, adjust the power of two in ST(1) and set
6524 235 ; the denormal count value
6526 237 ; Assert 0 <= ST(0) < 1.0
6528 008D D9E8 239 fld1 ; Load constant to normalize fraction
6530 008F 241 normalize_fraction
6532 008F DCC1 243 fadd st(1),st ; Set integer bit in fraction
6533 0091 DEE9 244 fsub ; Form normalized fraction in ST(0)
6534 0093 D9F4 245 fxtract ; Power of two field will be negative
6535 246 ; of denormal count
6536 0095 D9C9 247 fxch ; Put denormal count in ST(0)
6537 0097 DF15 248 fist word ptr [di] ; Put negative of denormal count in memory
6538 0099 DEC2 249 faddp st(2),st ; Form correct power of two in st(1)
6539 250 ; OK to use word ptr [di] now
6540 009B F71D 251 neg word ptr [di] ; Form positive denormal count
6541 009D 752B 252 jnz not_psuedo_zero
6543 254 ; A psuedo zero will appear as an unnormal number. When attempting
6544 255 ; to normalize it, the resultant fraction field will be zero. Performing
6545 256 ; an fxtract on zero will yield a zero exponent value.
6547 009F D9C9 258 fxch ; Put power of two value in st(0)
6548 00A1 DF1D 259 fistp wrd ptr [di] ; Set denormal count ot power of two value.
6549 260 ; Word ptr [di] is not used by convert
6550 261 ; integer, OK to leave running
6551 00A3 B0EAF8 262 sub dl,NORMAL-PSUEDO_ZERO ; Set return value saving the sign bit
6552 00A6 E9A400 263 jmp convert_integer ; Put zero value into memory
6554 265 ; The number is a real zero, set the return value and setup for
6555 266 ; conversion to BCD.
6559 00A9 80EAF0 270 sub dl,ZERO-NORMAL ; Convert status to normal value
6560 00AC E99E00 271 jmp convert_integer ; Treat the zero as an integer
6562 273 ; The number is a denormal. FXTRACT will not work correctly in this
6563 274 ; case. To correctly separate the exponent and fraction, add a fixed
6564 275 ; constant to the exponent to guarantee the rsult is not a denormal.
6566 00AF 277 found_denormal:
6568 00AF D9E8 279 fld1 ; Prepare to bump exponent
6570 00B3 D9F8 281 fprem ; Force denormal to smallest representable
6571 282 ; extended real format exponent
6572 00B5 D9F4 283 fxtract ; This will work correctly now
6574 285 ; The power of the original enormal value has been safely isolated.
6575 286 ; Check if the fraction value is an unnormal.
6577 00B7 D9E5 288 fxam ; See if the fraction is an unnormal
6578 00B9 9BDFE0 289 fstsw ax ; Save 80287 status in CPU AX reg for later
6579 00BC D9C9 290 fxch ; Put exponent in ST(0)
6580 00BE D9CA 291 fxch st(2) ; Put 1.0 into ST(0), exponent in ST(2)
6581 00C0 80EAFA 292 sub dl,DENORMAL-NORMAL ; Return normal status with correct sign
6582 00C3 A90044 293 test ax,4400H ; See if C0=C2=0 impling unnormal or NAN
6583 00C6 74C7 294 jz normalize_fraction ; Jump if fraction is an unnormal
6585 00C8 DDD8 296 fstp st(0) ; Remove unnecessary 1.0 from st(0)
6587 298 ; Calculate the decimal magnitude associated with this number to
6588 299 ; within one order. This error will always be inevitable due to
6589 300 ; rounding and lost precision. As a result, we will deliberately fail
6590 301 ; to consider the LOQ10 of the fraction value in calcuating the order.
6591 302 ; Since the fraction will always be 1 <= F < 2, its LOQ10 will not change
6592 303 ; the basic accuracy of the function. To get the decimal order of magnitude,
6593 304 ; simply multiply the power of two by LOQ10(2) and truncate the result to
6596 00CA 307 normal_value:
6597 00CA 308 not_pseudo_zero:
6599 00CA DB7EF0 310 fstp fraction ; Save the fraction field for later use
6600 00CD DF56FC 311 fist power_two ; Save power of two
6601 00D0 D9EC 312 fldlg2 ; Get LOQ10(2)
6602 313 ; Power_two is now safe to use
6603 00D2 DEC9 314 fmul ; Form LOQ10(of exponent of number)
6604 00D4 DF5EFA 315 fistp power_ten ; Any rounding mode will work here
6606 317 ; Check if the magnitude of the number rules out treating it as
6609 320 ; CX has the maximum number of decimal digits allowed.
6611 00D7 7B 322 fwait ; Wait for power_ten to be valid
6612 00D8 3B46FA 323 mov ax,power_ten ; Get power of ten of value
6613 00DB 2BC1 324 sub ax,cx ; Form scaling factor necessary in ax
6614 00DD 7722 325 ja adjust_result ; Jump if number will not fit
6616 327 ; The number is between 1 and 10**(field_size).
6617 328 ; Test if it is an integer.
6619 00DF 0F46FC 330 fild power_two ; Restore original number
6620 00E2 8BF2 331 mov si,dx ; Save return value
6621 00E4 80EAFE 332 sub dl,NORMAL-EXACT ; Convert to exact return value
6622 00E7 0B6EF0 333 fld fraction
6623 00EA 09FD 334 fscale ; Form full value, this is safe here
6624 00EC DDD1 335 fst st(1) ; Copy value for compare
6625 00EE 09FC 336 frndint ; Test if its an integer
6626 00F0 08D9 337 fcomp ; Compare values
6627 00F2 7BDD7EFE 338 fstsw status ; Save status
6628 00F6 F746FE0040 339 test status,4000H ; C3=1 implies it was an integer
6629 00FB 7550 340 jnz convert_integer
6631 00FD DDD8 342 fstp st(0) ; Remove non integer value
6632 00FF 8BD6 343 mov dx,si ; Restore original return value
6634 345 ; Scale the number to within the range allowed by the BCD format
6635 346 ; The scaling operation should produce a number within one decimal order
6636 347 ; of magnitude of the largest decimal number representable within the
6637 348 ; given string width.
6639 350 ; The scaling power of ten value is in ax.
6641 0101 352 adjust_result:
6643 0101 8907 354 mov word ptr [bx],ax ; Set initial power of ten return value
6644 0103 F7D8 355 neg ax ; Substract one for each order
6645 356 ; of magnitude the value is scaled by
6646 0105 E80000 E 357 call get_power_10 ; Scaling factor is returned as exponent
6648 0108 DB6EF0 359 fld fraction ; Get fraction
6649 010B DEC9 360 fmul ; Combine fractions.
6650 010D 8BF1 361 mov si,cx ; Form power of ten of the maximum
6651 010F D1E6 362 shl si,1 ; BCD value to fit in the string
6652 0111 D1E6 363 shl si,1 ; Index in si
6653 0113 D1E6 364 shl si,1
6654 0115 DF46FC 365 fild power_two ; Combine powers of two
6655 0118 DEC2 366 faddp st(2),st
6656 011A D9FD 367 fscale ; Form full value, exponent was safe
6657 011C DDD9 368 fstp st(1) ; Remove exponent
6659 370 ; Test the adjusted value against a table of exact powers of ten.
6660 371 ; The combined errors of the magnitude estimate and power function
6661 372 ; result in a value one order of magnitude too small or too large to fit
6662 373 ; correctly in the BCD field. To handle this problem, pretest the
6663 374 ; adjusted value, if it is too small or large, then adjust it by ten and
6664 375 ; adjust the power of ten value.
6666 011E 377 test_power:
6667 011E 2EDC940800 E 378
6668 379 fcom power_table[si]_type power_table; Compare against exact power
6669 380 ; entry. Use the next entry since cx
6670 381 ; has been decremented by one.
6671 0123 9BDFE0 382 fstsw ax ; No wait is necessary
6672 0126 690041 383 test ax,4100H ; If C3 = C0 = 0 then too big
6673 0129 750C 384 jnz text_for_small
6675 012B 2EDE360000 R 386 fidiv const10 ; Else adjust value
6676 0130 80E2FD 387 and dl,not EXACT ; Remove exact flag
6677 0133 FF07 388 inc word ptr [bx] ; Adjust power of ten value
6678 0135 EB14 389 jmp short in_range ; Convert the value to a BCD integer
6680 0137 391 test_for_small
6682 0137 2EDC940000 E 393 fcom power_table[si] ; Test relative size
6683 013C 9BDFE0 394 fstsw ax ; No wait is necessary
6684 013F A90001 395 test ax,100H ; If C0 = 0 then st(0) >= lower bound
6685 0142 7407 396 jz in_range ; Convert the value to a BCD integer
6687 0144 2EDE0E0000 R 398 fimul const10 ; Adjust value into range
6688 0149 FF0F 399 dec word ptr [bx] ; Adjust power of ten value
6692 014B D9FC 403 frndint ; Form integer value
6694 405 ; Assert: 0 <= TOS <= 999,999,999,999,999,999
6695 406 ; The TOS number will be exactly representable in 18 digit BCD format
6697 014D 408 convert_integer:
6699 014D DF76F0 410 fbstp bcd_value ; Store ax BCD format number
6701 412 ; While the store BCD runs, setup registers for the conversion to
6704 0150 BE0800 415 mov si,BCD_SIZE-2 ; Initial BCD index value
6705 0153 B9040F 416 mov cx,0f04h ; Set shift count and mask
6706 0156 BB0100 417 mov bx,1 ; Set initial size of ASCII field for sign
6707 0159 8B730C 418 mov di,string_ptr ; Get address of start of ASCII string
6708 015C BCD8 419 mov ax,ds ; Copy ds to es
6709 015E BEC0 420 mov es,ax
6710 0160 FC 421 cld ; Set autoincrement mode
6711 0161 B02B 422 mov al,'+' ; Clear sign field
6712 0163 F6C201 423 text dl,MINUS ; Look for negative value
6713 0166 7402 424 jr positive_result
6715 0168 B02D 426 mov al,'-'
6717 016A 428 positive_result:
6719 016A AA 430 stash ; Bump string pointer past sign
6720 016B 809E2FE 431 and dl,not MINUS ; Turn off sign bit
6721 016E 9B 432 fwait ; Wait for fbstp to finish
6723 434 ; Register usage:
6724 435 ; ah: BCD byte value in use
6725 436 ; al: ASCII character value
6726 437 ; dx: Return value
6727 438 ; ch: BCD mask = ofh
6728 439 ; cl BCD shift count = 4
6729 440 ; bx: ASCII string field width
6730 441 ; si: BCD field index
6731 442 ; di: ASCII string field pointer
6732 443 ; ds,es: ASCII string segment base
6734 445 ; Remove leading zeroes from the number.
6736 016F 447 skip_leading_zeroes
6738 016F 8A62F0 449 move ah,bcd_byte[si] ; Get BCD byte
6739 0172 BAC4 450 move al,ah ; Copy value
6740 0174 D2E8 451 shr al,cl ; Get high order digit
6741 0176 22C5 452 and al,ch ; Set zero flag
6742 0178 7516 453 jnz enter_odd ; Enter loop if leading non zero found
6744 017A 8AC4 455 mov al,ah ; Get BCD byte again
6745 017C 22C5 456 and al,ch ; Get low order digit
6746 017E 7518 457 jnz enter_even
6748 0180 4E 459 dec si ; Decrement BCD index
6749 0181 79EC 460 jns skip_leading_zeroes
6751 462 ; The significand was all zeroes
6753 0183 B030 464 mov al,'0' ; Set initial zero
6755 0186 43 466 inc bx ; Bump string length
6756 0187 EB16 467 jmp short exit_with_value
6758 469 ; Now expand the BCD string into digit per byte values 0-9
6762 0189 8A62F0 473 mov ah,bcd_byte[si] ; Get BCD byte
6763 018C 8AC4 474 mov al,ah
6764 018E D2E8 475 shr al,cl ; Get high order digit
6768 0190 0430 479 add al,'0' ; Convert to ASCII
6769 0192 AA 480 stosb ; Put digit into ASCII string area
6770 0193 8AC4 481 mov al,ah ; Get low order digit
6771 0195 22C5 482 and al,ch
6772 0197 43 483 inc bx ; Bump field size counter
6774 0198 0430 485 enter_even
6776 019B 43 487 add al,'0' ; Convert to ASCII
6777 019C 4E 488 stosb ; Put digit into ASCII area
6778 019D 79EA 489 inc bx ; Bump field size counter
6779 490 dec si ; Go to next BCD byte
6782 493 ; Conversion complete. Set the string size and remainder
6784 019F 495 exit_with_value:
6786 019F 8B7E0A 497 move di,size_ptr
6787 01A2 891D 498 mov word ptr [di],bx
6788 01A4 8BC2 499 mov ax,x ; Set return value
6789 01A6 E980FE 500 jmp exit_proc
6791 502 floating_to_ascii endp
6794 ASSEMBLY COMPLETE, NO WARNINGS, NO ERRORS
6797 iAPX286 MACRO ASSEMBLER Calculate the value of 10**ax 12:11:08 09/25/83 PAGE 1
6799 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE GET_POWER_10
6800 OBJECT MODULE PLACED IN :F3:POW10.OBJ
6801 ASSEMBLER INVOKED BY: ASM286.86 :F3:POW10.AP2
6805 1 +1 $title("Calculate the value of 10**ax")
6807 3 ; This subroutine will calculate the value of 10**ax.
6808 4 ; For values of 0 <= ax <19, the result will exact.
6809 5 ; All 80286 registers are transparent and the value is returned on
6810 6 ; the TOS as two numbers, exponent in ST(1) and fraction in ST(0).
6811 7 ; The exponent value can be larger than the largest exponent of an
6812 8 ; extended real format number. Three stack entries are used.
6814 10 name get_power_10
6816 12 public get_power_10,power_table
6818 ---- 14 stack stackseg 8
6820 ---- 16 code segment or public
6822 18 ; Use exact values from 1:0 to 1e18
6824 20 even ; Optimize 16 bit access
6825 0000 000000000000F0 21 power_table dq 1.0,1e1,1e2,1e3
6833 0020 000000000088C3 22 dq 1e4,1e5,1e6,1e7
6841 0040 0000000084D797 23 dq 1e8,1e9,1e10,1e11
6849 0060 000000A2941A6D 24 dq 1e12,1e13,1e14,1e15
6857 0080 0080E03779C341 25 dq 1e16,1e17,1e18
6864 27 get_power_10 proc
6866 009B 770F 29 cmp ax,18 ; Test for 0 <= ax < 19
6869 009E 8BD8 32 push bx ; Get working index register
6870 00A0 C1E303 33 mov bx,ax ; Form table index
6871 00A3 2EDD870000 R 34 shl bx,3
6872 00A8 5B 35 fld power_table[bx] ; Get exact value
6873 00A9 D9F4 36 pop bx ; Restore register value
6874 00AB C3 37 fxtract ; Separate power and fraction
6875 38 ret ; OK to leave fxtract running
6877 40 ; Calculate the value using the exponentiate instruction.
6878 41 ; The following relations are used:
6879 42 ; 10**x = 2**(log2(10)*x)
6880 43 ; 2**(I+F) = 2**I * 2**F
6881 44 ; if st(1) = I and st(0) = 2**F then fscale produces 2**(I+F)
6883 00AC 46 out_of_range:
6885 00AC D9E9 48 fld12t ; TOS = LOG2(10)
6886 00AE C8040000 49 enter 4.0 ; Format stack
6887 00B2 8946FE 50 mov [bp-2],ax ; Save power of 10 value
6888 00B5 DE4EFE 51 fimul word ptr [bp-1] ; TOS, x= LOG2(10)*P = LOG2(10**P)
6889 00B8 9BD97EFC 52 fstcw word ptr [bp-4] ; Get current control word
6890 00BC 8B46FC 53 mov ax,word ptr [bp-4] ; Get control word, no wait necessary
6891 00BF 25FFF3 54 and ax,not OCOOH ; Mask off current rounding field
6892 00C2 0D0004 55 or ax,0400H ; Set round to negative infinity
6893 00C5 6746FC 56 xchg ax,word ptr [bp-4] ; Put new control word in memory
6894 57 ; old control word is in ax
6895 00C8 D9E8 58 fld1 ; Set TOS = -1.0
6897 00CC D9C1 60 fld st(1) ; Copy power value in base two
6898 00CE D96EFC 61 fldcw word ptr [bp-4] ; Set new control word value
6899 00D1 D9FC 62 frndint ; TOS = I: -inf < I <= X, I is an integer
6900 00D3 8946FC 63 mov word ptr [bp-4],ax ; Restore original rounding control
6901 00D6 D96EFC 64 fldcw word ptr [bp-4]
6902 00D9 D9CA 65 fxch st(2) ; TOS = X, ST(1) = -1.0, St(2) = I
6903 00DB DBE2 66 fsub st,st(2) ; TOS,F=X-I; 0 <= TOS < 1.0
6904 00DD 8B46FE 67 mov ax,[bp-2] ; Restore power of ten
6905 00E0 D9FD 68 fscale ; TOS = F/2: 0 <= TOS < 0.5
6906 00E2 D9F0 69 f2xm1 ; TOS = 2**(F/2) - 1.0
6907 00E4 C9 70 leave ; Restore stack
6908 00E5 DEE1 71 fsubr ; Form 2**(F/2)
6909 00E7 DCC8 72 fmul st,st(0) ; Form 2**F
6910 00E9 C3 73 ret ; OK to leave fmul running
6912 75 get_power_10 endp
6916 ASSEMBLY COMPLETE, NO WARNINGS, NO ERRORS
6919 iAPX286 MACRO ASSEMBLER Determine TOS register contents 12:12:13 09/25/83 PAGE 1
6921 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE TOS_STATUS
6922 OBJECT MODULE PLACED IN :F3:T0SST.OBJ
6923 ASSEMBLER INVOKED BY: ASM286.86 :F3:TOSST.AP2
6927 1 +1 $title("Determine TOS register contents")
6929 3 ; This subroutine will return a value from 0-15 in AX corresponding
6930 4 ; to the contents of 80287 TOS. All registers are transparent and no
6931 5 ; errors are possible. The return value corresponds to c3,c2,c1,c0
6932 6 ; of FXAM instruction.
6936 10 public tos_status
6938 ---- 12 stack stackseg 6 ; Allocate space on the stack
6940 ---- 14 code segment er public
6942 0000 16 tos_status proc
6944 0000 D9E5 18 fxam ; Get register contents status
6945 0002 9BDFE0 19 fstsw ax ; Get status
6946 0005 8AC4 20 mov al,ah ; Put bit 10-8 into bits 2-0
6947 0007 250740 21 and ax,4007h ; Mask out bits c3,c2,c1,c0
6948 000A C0EC03 22 shr ah,3 ; Put bit c3 into bit 11
6949 000D 0AC4 23 or al,ah ; Put c3 into bit 3
6950 000F B400 24 mov ah,0 ; Clear return value
6957 ASSEMBLY COMPLETE, NO WARNINGS, NO ERRORS
6960 Function Partitioning
6961 Three separate modules implement the conversion. Most of the work of the
6962 conversion is done in the module FLOATING_TO_ASCII. The other modules are
6963 provided separately, because they have a more general use. One of them,
6964 GET_POWER_10, is also used by the ASCII to floating-point conversion
6965 routine. The other small module, TOS_STATUS, will identify what, if
6966 anything, is in the top of the numeric register stack.
6969 Exception Considerations
6970 Care is taken inside the function to avoid generating exceptions. Any
6971 possible numeric value will be accepted. The only exceptions possible would
6972 occur if insufficient space exists on the numeric register stack.
6974 The value passed in the numeric stack is checked for existence, type (NaN
6975 or infinity), and status (unnormal, denormal, zero, sign). The string size
6976 is tested for a minimum and maximum value. If the top of the register stack
6977 is empty, or the string size is too small, the function will return with an
6980 Overflow and underflow is avoided inside the function for very large or
6984 Special Instructions
6985 The functions demonstrate the operation of several numeric instructions,
6986 different data types, and precision control. Shown are instructions for
6987 automatic conversion to BCD, calculating the value of 10 raised to an
6988 integer value, establishing and maintaining concurrency, data
6989 synchronization, and use of directed rounding on the NPX.
6991 Without the extended precision data type and built-in exponential function,
6992 the double precision accuracy of this function could not be attained with
6993 the size and speed of the shown example.
6995 The function relies on the numeric BCD data type for conversion from binary
6996 floating-point to decimal. It is not difficult to unpack the BCD digits into
6997 separate ASCII decimal digits. The major work involves scaling the
6998 floating-point value to the comparatively limited range of BCD values. To
6999 print a 9-digit result requires accurately scaling the given value to an
7000 integer between 10^(8) and 10^(9). For example, the number +0.123456789
7001 requires a scaling factor of 10^(9) to produce the value +123456789.0,
7002 which can be stored in 9 BCD digits. The scale factor must be an exact
7003 power of 10 to avoid to changing any of the printed digit values.
7005 These routines should exactly convert all values exactly representable in
7006 decimal in the field size given. Integer values that fit in the given string
7007 size will not be scaled, but directly stored into the BCD form. Noninteger
7008 values exactly representable in decimal within the string size limits will
7009 also be exactly converted. For example, 0.125 is exactly representable in
7010 binary or decimal. To convert this floating-point value to decimal, the
7011 scaling factor will be 1000, resulting in 125. When scaling a value, the
7012 function must keep track of where the decimal point lies in the final
7016 Description of Operation
7017 Converting a floating-point number to decimal ASCII takes three major
7018 steps: identifying the magnitude of the number, scaling it for the BCD data
7019 type, and converting the BCD data type to a decimal ASCII string.
7021 Identifying the magnitude of the result requires finding the value X such
7022 that the number is represented by I*10^(X), where 1.0 <= I < 10.0. Scaling
7023 the number requires multiplying it by a scaling factor 10^(S), so that the
7024 result is an integer requiring no more decimal digits than provided for in
7027 Once scaled, the numeric rounding modes and BCD conversion put the number
7028 in a form easy to convert to decimal ASCII by host software.
7030 Implementing each of these three steps requires attention to detail. To
7031 begin with, not all floating-point values have a numeric meaning. Values
7032 such as infinity, indefinite, or Not a Number (NaN) may be encountered by
7033 the conversion routine. The conversion routine should recognize these
7034 values and identify them uniquely.
7036 Special cases of numeric values also exist. Denormals, unnormals, and
7037 pseudo zero all have a numeric value but should be recognized, because all
7038 of them indicate that precision was lost during some earlier calculations.
7040 Once it has been determined that the number has a numeric value, and it is
7041 normalized setting appropriate unnormal flags, the value must be scaled to
7046 To scale the number, its magnitude must be determined. It is sufficient to
7047 calculate the magnitude to an accuracy of 1 unit, or within a factor of 10
7048 of the given value. After scaling the number, a check will be made to see if
7049 the result falls in the range expected. If not, the result can be adjusted
7050 one decimal order of magnitude up or down. The adjustment test after the
7051 scaling is necessary due to inevitable inaccuracies in the scaling value.
7053 Because the magnitude estimate need only be close, a fast technique is
7054 used. The magnitude is estimated by multiplying the power of 2, the unbiased
7055 floating-point exponent, associated with the number by log{10}2. Rounding
7056 the result to an integer will produce an estimate of sufficient accuracy.
7057 Ignoring the fraction value can introduce a maximum error of 0.32 in the
7060 Using the magnitude of the value and size of the number string, the scaling
7061 factor can be calculated. Calculating the scaling factor is the most
7062 inaccurate operation of the conversion process. The relation
7063 10^(X)=2**(X * log{2}10) is used for this function. The exponentiate
7064 instruction (F2XM1) will be used.
7066 Due to restrictions on the range of values allowed by the F2XM1
7067 instruction, the power of 2 value will be split into integer and fraction
7068 components. The relation 2**(I + F) = 2**I * 2**F allows using the FSCALE
7069 instruction to recombine the 2**F value, calculated through F2XM1, and the
7073 Inaccuracy in Scaling
7074 The inaccuracy of these operations arises because of the trailing zeros
7075 placed into the fraction value when stripping off the integer valued bits.
7076 For each integer valued bit in the power of 2 value separated from the
7077 fraction bits, one bit of precision is lost in the fraction field due to
7078 the zero fill occurring in the least significant bits.
7080 Up to 14 bits may be lost in the fraction because the largest allowed
7081 floating point exponent value is 2^(14) - 1.
7084 Avoiding Underflow and Overflow
7085 The fraction and exponent fields of the number are separated to avoid
7086 underflow and overflow in calculating the scaling values. For example, to
7087 scale 10^(4932) to 10^(8) requires a scaling factor of 10^(4950), which
7088 cannot be represented by the NPX.
7090 By separating the exponent and fraction, the scaling operation involves
7091 adding the exponents separate from multiplying the fractions. The exponent
7092 arithmetic will involve small integers, all easily represented by the NPX.
7096 It is possible that the power function (Get_Power_10) could produce a
7097 scaling value such that it forms a scaled result larger than the ASCII field
7098 could allow. For example, scaling 9.9999999999999999 * 10^(4900) by
7099 1.00000000000000010 * 10^(-4883) would produce 1.00000000000000009 *
7100 10^(18). The scale factor is within the accuracy of the NPX and the result
7101 is within the conversion accuracy, but it cannot be represented in BCD
7102 format. This is why there is a post-scaling test on the magnitude of the
7103 result. The result can be multiplied or divided by 10, depending on whether
7104 the result was too small or too large, respectively.
7108 For maximum flexibility in output formats, the position of the decimal
7109 point is indicated by a binary integer called the power value. If the power
7110 value is zero, then the decimal point is assumed to be at the right of the
7111 rightmost digit. Power values greater than zero indicate how many trailing
7112 zeros are not shown. For each unit below zero, move the decimal point to the
7115 The last step of the conversion is storing the result in BCD and indicating
7116 where the decimal point lies. The BCD string is then unpacked into ASCII
7117 decimal characters. The ASCII sign is set corresponding to the sign of the
7121 Trigonometric Calculation Examples
7122 The 80287 instruction set does not provide a complete set of trigonometric
7123 functions that can be used directly in calculations. Rather, the basic
7124 building blocks for implementing trigonometric functions are provided by the
7125 FPTAN and FPREM instructions. The example in figure 4-7 shows how three
7126 trigonometric functions (sine, cosine, and tangent) can be implementing
7127 using the 80287. All three functions accept a valid angle argument between
7128 -2^(62) and +2^(62). These functions may be called from PL/M-286,
7129 Pascal-286, FORTRAN-286, or ASM286 routines.
7131 These trigonometric functions use the partial tangent instruction together
7132 with trigonometric identities to calculate the result. They are accurate to
7133 within 16 units of the low 4 bits of an extended precision value. The
7134 functions are coded for speed and small size, with tradeoffs available for
7137 Figure 4-7. Calculating Trigonometric Functions
7140 iAPX286 MACRO ASSEMBLER 80287 Trigonometric functions 10:13:51 09/25/83 PAGE 1
7142 SERIES-888 iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE TRIG_FUNCTIONS
7143 OBJECT MODULE PLACED IN :F3:TRIG.OBJ
7144 ASSEMBLER INVOKED BY: ASM286.86 :F3:TRIG.AP2
7148 1 +1 $title("80287 Trigonometric Functions")
7150 3 name trig_functions
7151 4 public sine,cosine,tangent
7153 ---- 6 stack stackseg 6 ; Reserve local space
7155 # 8 sw_287 record res1:1,cond3:1,top:3,cond2:1,cond1:1,cond0:1,
7158 ---- 11 code segment er public
7160 13 ; Define local constants
7163 0000 35C26821A2DA0F 16 pi_quarter dt 3FFEC90FDAA22168C235R ; PI/4
7165 000A 0000C0FF 17 indefinite dd 0FFC000000R ; Indefinite special value
7168 20 ; This subroutine calculates the sine or cosine of the angle, given in
7169 21 ; radians. The angle is in ST(0), the returned value will be in ST(0).
7170 22 ; The result is accurate to within 7 units of the least significant three
7171 23 ; bits of the NPX extended real format. The PLM/86 definition is:
7173 25 ; sine: procedure (angle) real external,
7174 26 ; declare angle real;
7177 29 ; cosine: procedure (angle) real external;
7178 30 ; declare angle real;
7181 33 ; Three stack registers are required. The result of the function
7182 34 ; defined as follows for the following arguments:
7186 38 ; valid or unnormal less than 2**62 in magnitude correct value
7188 40 ; denormal correct denormal
7189 41 ; valid or unnormal greater than 2**62 indefinite
7190 42 ; infinity indefinite
7195 47 ; This function is based on the NPX fptan instruction. The fptan
7196 48 ; instruction will only work with an angle of from 0 to PI/4. With this
7197 49 ; instruction, the sine or cisone of angles from 0 to PI/4 can be accurately
7198 50 ; calculated. The technique used by this routine can calculate a general
7199 51 ; sine or cosine by using one of four possible operations:
7201 53 ; Let R = |angle mod PI/4|
7202 54 ; S = -1 or 1, according to the sign of the angle
7204 56 ; 1) sin(R) 2) cos(R) 3) sin(PI/4-R) 4) cos(PI/4-R)
7206 58 ; The choice of the relation and the sign of the result follows
7207 59 ; decision table shown below based on the octant the angle falls in:
7209 61 ; octant sine cosine
7222 74 ; Angle to sine function is a zero or unnormal
7224 000E 76 sine_zero_unnormal:
7226 000E DDD9 78 fstp st(1) ; Remove PI/4
7227 0010 7501 79 jnz enter_sine_normalize ; Jump if angle is unnormal
7229 81 ; Angle is a zero.
7233 85 ; Angle is an unnormal
7235 0013 87 enter_sine_normalize:
7237 0013 E80901 89 call normalize_value
7238 0016 EB2F 90 jmp short enter_sine
7240 0018 92 cosine proc ; Entry point to cosine
7242 0018 D9E5 94 fxam ; Look at the value
7243 00A1 9BDF30 95 fstsw ax ; Store status value
7244 001D 2EDB2E0000 R 96 fld pi_quarter ; Setup for angle reduce
7245 0022 B101 97 mov c1,1 ; Signal cosine function
7246 0024 9E 98 sahf ; ZF = C3, PF = C2, CF = C0
7247 0025 7263 99 jc funny_parameter ; Jump if parameter is
7248 100 ; empty, NAN, or infinity
7250 102 ; Angle is unnormal, normal, zero, denormal.
7252 0027 D9C9 104 fxch ; st(0) = angle, st(1) = PI/4
7253 0029 7A1C 105 jpe enter_sine ; Jump if normal or denormal
7255 107 ; Angle is an unnormal or zero
7257 002B DDD9 109 fstp st(1) ; Remove PI/4
7258 002D 75E4 110 jnz enter_sine_normalize
7260 112 ; Angle is a zero, cos(0) = 1.0
7262 002F DDD8 114 fstp st(0) ; Remove 0
7263 0031 D9E8 115 fldl ; Return 1
7266 118 ; All work is done as a sine function. By adding PI/2 to the angle
7267 119 ; a cosine is converted to a sine. Of course the angle addition is not
7268 120 ; done to the argument but rather to the program logic control values.
7270 0034 122 sine ; Entry point for sine function
7272 0034 D9E5 124 fxam ; Look at the parameter
7273 0036 9BDFE0 125 fstsw ax ; Look at fxam status
7274 0039 2EDB2E0000 R 126 fld pi_quarter ; Get PI/4 value
7275 003E 9E 127 sahf ; CF = C0, PF = C2, ZF - C3
7276 003F 7249 128 jc funny_parameter ; Jump if empty, NAN, or infinity
7278 130 ; Angle is unnormal, normal, zero, or denormal
7280 0041 D9C9 132 fxch ; ST(1) = PI/4, st(0) angle
7281 0043 B100 133 mov c1,0 ; Signal sine
7282 0045 7BC7 134 jpo sine_zero_unnormal ; Jump if zero or unnormal
7284 136 ; ST(0) is either a normal or denormal value. Both will work
7285 137 ; Use the fprem instruction to accurately reduce the range of the given
7286 138 ; angle to within 0 and PI/4 in magnitude. If fprem cannot reduce the
7287 139 ; angle in one shot, the angle is too big to be meaningful, >2**62
7288 140 ; radians. Any roundoff error in the calculation of the angle given
7289 141 ; could completely change the result of this function. It is safest to
7290 142 ; call this very rare case an error.
7293 0047 D9F8 145 fprem ; Reduce angle
7294 146 ; Note that fprem will force a
7295 147 ; denormal to a very small unnormal
7296 148 ; Fptan of a very small unnormal
7297 149 ; will be the same very small
7298 150 ; unnormal, which is correct.
7299 0049 93 151 xchg ax,bx ; Save old status in BX
7300 004A 9BDFE0 152 fstsw ax ; Check if reduction was complete
7301 153 ; Quotient in C0,C3,C1
7302 004D 93 154 xchg ax,bx ; Put new status in bx
7303 004E F6C704 155 test bh,high(mask cond2) ; sin(2*N*PI+x) = sin(x)
7304 0051 7544 156 jnz angle_too_big
7306 158 ; Set sign flags and test for which eighth of the revolution the
7307 159 ; angle fell intl.
7309 161 ; Assert -PI/4 < st(0) < PI/4
7311 0053 D9E1 163 fabs ; Force the argument positive
7312 164 ; cond1 bit in bx holds the sign.
7313 0055 0AC9 165 or c1,c1 ; Test for sine or cosine function
7314 0057 740F 166 jz sine_select ; Jump if sine function
7316 168 ; This is a cosine function. Ignore the original sign of the angle
7317 169 ; and add a quarter revolution to the octant id from the fprem instruction
7318 170 ; cos(A) = sin(A+PI/2) and cos(|A|) = cos(A)
7320 0059 B0E4FD 172 and ah,not high(mask cond1) ; Turn off sign of argument
7321 005C B0CF80 173 or by,80H ; Prepare to add 010 to c0,c3,c1
7322 174 ; status value in ax
7323 175 ; Set busy bit so carry out from
7324 005F 80C740 176 add bh,high(mask cond3) ; C3 will go into the carry flag
7325 0062 B000 177 mov al,0 ; Extract carry flag
7326 0064 D0D0 178 rcl al,1 ; Put carry flag in low bit
7327 0066 32FB 179 xor bh,al ; Add carry to C0 not changing
7330 182 ; See if the argument should be reversed, depending on the octant in
7331 183 ; which the argument fell during fprem.
7333 0068 185 sine_select:
7335 0068 F6C702 187 test bh,high(mask cond1) ; Reverse angle if C1 = 1
7336 006B 7404 188 jz no_sine_reverse
7338 190 ; Angle was in octants 1,3,5,7.
7340 006D DEE9 192 fsub ; Invert sense of rotation
7341 006F EB0E 193 jmp short do_sine_fptan ; 0 < arg <= PI/4
7343 195 ; Angle was in octants 0,2,4,6
7344 196 ; Test for a zero argument since fptan will not work if st(0) = 0
7346 0071 198 no_sine_reverse:
7348 0071 D9E4 200 ftst ; Test for zero angle
7349 0073 91 201 xchg ax,cx
7350 0074 9BDFE0 202 fstsw ax ; cond3 = 1 if st(0) = 0
7351 0077 91 203 xchg ax,cx
7352 0078 DDD9 204 fstp st(1) ; Remove PI/4
7353 007A F6C540 205 test ch,high(mask cond3) ; If c3=1, argument is zero
7354 007D 7514 206 jnz sine_argument_zero
7356 208 ; Assert: 0 < st(0) <= PI/4
7358 007F 210 do_sine_fptan:
7360 007F D9F2 212 fptan ; TAN ST(0) = ST(1)/ST(0) = Y/X
7362 0081 214 after_sine_fptan:
7364 0081 F6C742 216 test bh,high(mask cond3 + mask cond1); Look at octant angle fell into
7365 0084 7B1A 217 jpo x_numerator ; Calculate cosine for octants
7368 220 ; Calculate the sine of the argument
7369 221 ; sine(A) = tan(A)/sqrt(1+tan(A)**2) if tan(A) = Y/X then
7370 222 ; sin(A) = Y/sqrt(X*X + Y*Y)
7372 0086 D9C1 224 fld st(1) ; Copy Y value
7373 0088 EB1A 225 jmp short finish_sine ; Put Y value in numerator
7375 227 ; The top of the stack is either NAN, infinity, or empty
7377 008A 229 funny_parameter:
7379 008A DDD8 231 fstp st(0) ; Remove PI/4
7380 008C 7404 232 jz return_empty ; Return empty if no parm
7382 008E 7B02 234 jpo return_NAN ; Jump if st(0) is NAN
7384 236 ; st(0) is infinity. Return an indefinite value.
7386 0090 D9F8 238 fprem ; ST(1) can be anything
7388 0092 240 return_NAN:
7389 0092 241 return_empty:
7391 0092 C3 243 ret ; OK to leave fprem running
7393 245 ; Simulate fptan with st(0) = 0
7395 0093 247 sine_argument_zero:
7397 0093 D9EB 249 fld1 ; Simulate tan(0)
7398 0095 EBEA 250 jmp after_sine_fptan ; Return the zero value
7400 252 ; The angle was too large. Remove the modulus and dividend from the
7401 253 ; stack and return an indefinite result.
7403 0097 255 angle_too_big:
7405 0097 DED9 257 fcompp ; Pop two values from the stack
7406 0099 2ED9060A00 R 258 fld indefinite ; Return indefinite
7407 009E 9B 259 fwait ; Wait for load to finish
7410 262 ; Calculate the cosine of the argument
7411 263 ; cos(A) = 1/sqrt(1+tan(A)**2) if tan(A) - Y/X then
7412 264 ; cos(A) = X/sqrt(X*X + Y*Y)
7414 00A0 266 X_numerator:
7416 00A0 D9C0 268 fld st(0) ; Copy X value
7417 00A2 D9CA 269 fxch st(2) ; Put X in numerator
7419 00A4 271 finish_sine:
7421 00A4 DCCB 273 fmul st,st(0) ; Form X*X + Y*Y
7424 00AB DCC8 275 fmul st,st(0)
7425 00AA DEC1 276 fadd ; st(0) = X*X + Y*Y
7426 00AC D9FA 277 fsqrt ; st(0) = sqrt(X*X + Y*Y)
7429 280 ; Form the sign of th result. The two conditions are the C1 flag from
7430 281 ; FXAM in bh and the CO flag from fprem in ah
7432 00AE 80E701 283 and bh,high(mask cond0) ; Look at the fprem C0 flag
7433 00B1 80E402 284 and ah,high(mask cond1) ; Look at the fxam C1 flag
7434 00B4 0AFC 285 or bh,ah ; Even number of flags cancel
7435 00B6 7A02 286 jpe positive_sine ; Two negatives make a positive
7437 00B8 D9E0 288 fchs ; Forc result negative
7439 00BA 290 positive_sine:
7441 00BA DEF9 292 fdiv ; Form final result
7442 00BC C3 293 ret ; Ok to leave fdiv running
7447 298 ; This function will calculate the tangent of an angle.
7448 299 ; The angle, in radians is passed in ST(0), the tangent is returned
7449 300 ; in ST(0). The tangent is calculated to an accuracy of 4 units in the
7450 301 ; least three significant bits of an extended real format number. The
7451 302 ; PLM/86 calling format is:
7453 304 ; tangent procedure (angle) real external;
7454 305 ; declare angle real;
7457 308 ; Two stack registers are used. The result of the tangent function is
7458 309 ; defined for the following cases:
7462 313 ; valid or unnormal < 2**62 in magnitude correct value
7464 315 ; denormal correct denormal
7465 316 ; valid or unnormal > 2**62 in magnitude indefinite
7467 318 ; infinity indefinite
7470 321 ; The tangent instruction uses the fptan instruction. Four possible
7471 322 ; relations are used:
7473 324 ; Let R = |angle MOD PI/4|
7474 325 ; S = -1 or 1 depending on the sign of the angle
7476 327 ; 1) tan(R) 2) tan(PI/4-R) 3) 1/tan(R) 4) 1/tan(PI/4-R)
7478 329 ; The following table is used to decide which relation to use depending
7479 330 ; on in which octant the angle fell.
7481 332 ; octant relation
7492 00BD 343 tangent proc
7494 00BD D9E5 345 fram ; Look at the parameter
7495 00BF 9BDFE0 346 fstw ax ; Get fxam status
7496 00C2 2EDB2E0000 R 347 fld pi_quarter ; Get PI/4
7497 00C7 9E 348 sahf ; CF = C1, PF = C2, ZF = C3
7498 00C8 72C0 349 jc funny_parameter
7500 351 ; Angle is unnormal, normal, zero, or denormal.
7502 00CA D9C9 353 fxch ; st(0) = angle, st(1) = PI/4
7503 00CC 7A17 354 jpe tan_zero_unnormal
7505 356 ; Angle is either an normal or denormal.
7506 357 ; Reduc the angle to the range -PI/4 < result < PI/4
7507 358 ; If fprem cannot perform this operation in one try, the magnitude of the
7508 359 ; angle must be > 2**62. Such an angle is so large that any rounding
7509 360 ; errors could make a very large difference in the reduced angle.
7510 361 ; It is safest to call this very rare case an error.
7514 00CE D9F8 365 fprem ; Quotient in C0,C3,C1
7515 366 ; Convert denormals into unnormals
7516 00D0 93 367 xchg ax,bx
7517 00D1 9BDFE0 368 fstsw ax ; Quotient identifies octant
7518 369 ; original angle fell into
7519 00D4 93 370 xchg ax,bx
7520 00D5 F6C704 371 test bh,high(mask cond2) ; Test for complete reduction
7521 00D8 7BD 372 jnz angle_too_big ; Exit if angle was too big
7523 374 ; See if the angle must be reversed.
7525 376 ; Assert -PI/4 < st(0) < PI/4
7527 00DA D9E1 378 fabs ; 0 <= st(0) < PI/4
7528 379 ; C3 in bx has the sign flag
7529 00DC F6C702 380 test bh,high(mask cond1) ; must be reversed
7530 00DF 740E 381 jz no_tan_reverse
7532 383 ; Angle fell in octants 1,3,5,7. Reverse it, subtract it from PI/4.
7534 00E1 DEE9 385 fsub ; Reverse angle
7535 00E3 EB18 386 jmp short do_tangent
7537 388 ; Angle is either zero or an unnormal
7539 00E5 390 tan_zero_unnormal:
7541 00E5 DDD9 392 fstp st(1) ; Remove PI/4
7542 00E7 7405 393 jz tan_angle_zero
7544 395 ; Angle is an unnormal.
7546 00E9 E83300 397 call normalize_value
7547 00EC EBE0 398 jmp tan_normal
7549 00EE 400 tan_angle_zero:
7553 404 Angle fell in octants 0,2,4,6. Test for st(0) = 0, fptan won't work
7555 00EF 406 no_tan_reverse:
7557 00EF D9E4 408 ftst ; Test for zero angle
7558 00F1 91 409 xchg ax,cx
7559 00F2 9BDFE0 410 fstsw ax ; C3 = 1 if st(0) = 0
7560 00F5 91 411 fstp st(1)
7561 00F6 DDD9 412 test ch,high(mask cond3)
7562 00F8 F6C540 413 jnz tan_zero
7566 417 fptan ; tan ST(0) = ST(0)/ST(0)
7570 421 ; Decide on the order of the operands and their sign for the divide
7571 422 ; operation while the fptan instruction is working.
7573 424 mov al,bh ; Get a copy of fprem C3 flag
7574 00FF 8AC7 425 and ax,mask cond1 + high(mask cond3); Examine fprem C3 flag and
7575 0101 254002 426 ; FXAM C1 flag
7576 427 test bh,high(mask cond1 + mask cond3); Use reverse divide if in
7577 0104 F6C742 428 ; octants 1,2,5,6
7578 429 jpo reverse_divide ; Note: parity works on low
7579 0107 7B0D 430 ; 8 bits only!
7581 432 ; Angle was in octants 0,3,4,7
7582 433 ; Test for the sign of the result. Two negatives cancel.
7585 0109 0AC4 436 jpe positive_divide
7587 438 fchs ; Force result negative
7589 440 positive_divide:
7591 442 fdiv ; Form result
7592 010F DEF9 443 ret ; Ok to leave fdiv running
7596 447 fld1 ; Force 1/0 = tan(PI/2)
7598 0114 EBE9 449 ; Angle was in octants 1,2,5,6
7599 450 ; Set the correct sign of the result
7604 455 jpe positive_r_divide
7606 0118 7A02 457 fchs ; Force result negative
7608 011A D9E0 459 positive_r_divide:
7610 011C 461 fdivr ; Form reciprocal of result
7611 462 ret ; Ok to leave fdiv running
7613 011E C3F1 464 tangent endp
7615 466 ; This function will normalize the value in st(0)
7616 467 ; Then PI/4 is placed into st(1).
7618 469 normalize_value:
7620 011F 471 fabs ; Force value positive
7621 472 fxtract ; 0 <= st(0) < 1
7622 011F D9E1 473 fld1 ; Get normalize bit
7623 0121 D9F4 474 fadd st(1),st ; Normalize fraction
7624 0123 D9E8 475 fsub ; Resotre original value
7625 0125 DCC1 476 fscale ; Form original normalized value
7626 0127 DEE9 477 fstp st(1) ; Remove scale factor
7627 0129 D9FD 478 fld pi_quarter ; Get PI/4
7629 012D 2EDB2E0000 R 480 ret
7631 0134 C3 482 code ends
7636 ASSEMBLY COMPLETE, NO WARNINGS, NO ERRORS
7640 These trigonometric functions use the FPTAN instruction of the NPX. FPTAN
7641 requires that the angle argument be between 0 and Ò/4 radians, 0 to 45
7642 degrees. The FPREM instruction is used to reduce the argument down to this
7643 range. The low three quotient bits set by FPREM identify which octant the
7644 original angle was in.
7646 One FPREM instruction iteration can reduce angles of 10^(18) radians or less
7647 in magnitude to Ò/4! Larger values can be reduced, but the meaning of the
7648 result is questionable, because any errors in the least significant bits of
7649 that value represent changes of 45 degrees or more in the reduced angle.
7652 Cosine Uses Sine Code
7653 To save code space, the cosine function uses most of the sine function
7654 code. The relation sin (�A� + Ò/2) = cos(A) is used to convert the
7655 cosine argument into a sine argument. Adding Ò/2 to the angle is performed
7656 by adding 010{2} to the FPREM quotient bits identifying the argument's
7659 It would be very inaccurate to add Ò/2 to the cosine argument if it was
7660 very much differentfrom Ò/2.
7662 Depending on which octant the argument falls in, a different relation will
7663 be used in the sine and tangent functions. The program listings show which
7666 For the tangent function, the ratio produced by FPTAN will be directly
7667 evaluated. The sine function will use either a sine or cosine relation
7668 depending on which octant the angle fell into. On exit, these functions will
7669 normally leave a divide instruction in progress to maintain concurrency.
7671 If the input angles are of a restricted range, such as from 0 to 45
7672 degrees, then considerable optimization is possible since full angle
7673 reduction and octant identification is not necessary.
7675 All three functions begin by looking at the value given to them. Not a
7676 Number (NaN), infinity, or empty registers must be specially treated.
7677 Unnormals need to be converted to normal values before the FPTAN instruction
7678 will work correctly. Denormals will be converted to very small unnormals
7679 that do work correctly for the FPTAN instruction. The sign of the angle is
7680 saved to control the sign of the result.
7682 Within the functions, close attention was paid to maintain concurrent
7683 execution of the 80287 and host. The concurrent execution will effectively
7684 hide the execution time of the decision logic used in the program.
7687 Appendix A Machine Instruction Encoding and Decoding
7689 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7691 Machine instructions for the 80287 come in one of five different forms as
7692 shown in table A-1. In all cases, the instructions are at least two bytes
7693 long and begin with the bit pattern 11011B, which identifies the ESCAPE
7694 class of instructions. Instructions that reference memory operands are
7695 encoded much like similar CPU instructions, because all of the CPU
7696 memory-addressing modes may be used with ESCAPE instructions.
7698 Note that several of the processor control instructions (see table 2-11 in
7699 Chapter Two) may be preceded by an assembler-generated CPU WAIT instruction
7700 (encoding: 10011011B) if they are programmed using the WAIT form of their
7701 mnemonics. The ASM286 assembler inserts a WAIT instruction only before these
7702 specific processor control instructions‘‘all of the numeric instructions are
7703 automatically synchronized by the 80286 CPU and an explicit WAIT
7704 instruction, though allowed, is not necessary.
7706 Table A-2 lists all 80287 machine instructions in binary sequence. This
7707 table may be used to "disassemble" instructions in unformatted memory dumps
7708 or instructions monitored from the data bus. Users writing exception
7709 handlers may also find this information useful to identify the offending
7713 Table A-1. 80287 Instruction Encoding
7715 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
7716 � Lower-Addressed Byte � Higher-Addressed Byte � 0, 1, or 2 bytes �
7717 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘š‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
7719 Memory transfers, including applicable processor control instructions;
7720 0, 1, or 2 displacement bytes may follow.� 1 1 0 1 1 � OP-A � 1 � MOD � 1 �OP-B � R/M � DISPLACEMENT �
7721 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘š‘‘‘š‘‘‘‘‘‘‘š‘‘‘™‘‘‘‘‘š‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
7723 Memory arithmetic and comparison instructions; 0, 1, or 2 displacement
7724 bytes may follow.� 1 1 0 1 1 �FORMAT �OP-A MOD � OP-B � R/M � DISPLACEMENT �
7725 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘˜‘‘‘š‘‘‘š‘‘‘˜‘‘‘š‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
7727 Stack arithmetic and comparison instructions.� 1 1 0 1 1 � R � P �OP-A 1 � 1 � OP-B � REG �
7728 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘˜‘‘‘‘‘™‘‘‘‘‘‘‘—
7730 Constant, transcendental, some arithmetic instructions.� 1 1 0 1 1 � 0 � 0 � 1 � 1 � 1 � 1 � OP �
7731 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘—
7733 Processor control instructions that do not reference memory.� 1 1 0 1 1 � 0 � 1 � 1 � 1 � 1 � 1 � OP �
7734 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘•
7735 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
7737 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7740 OP, OP-A, OP-B: Instruction opcode, possibly split into two fields.
7742 MOD: Same as 80286 CPU mode field.
7744 R/M: Same as 80286 CPU register/memory field.
7746 FORMAT: Defines memory operand
7752 R: 0 = return result to stack top
7753 1 = return result to other register
7755 P: 0 = do not pop stack
7756 1 = pop stack after operation
7758 REG: register stack element
7761 010 = third stack element, etc.
7762 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7765 Table A-2. Machine Instruction Decoding Guide
7768 ’‘1st Byte‘‘“ ASM286 Instruction
7769 Hex Binary 2nd Byte Bytes 3, 4 Format
7771 D8 1101 1000 MOD00 0R/M (disp-lo),(disp-hi) FADD short-real
7772 D8 1101 1000 MOD00 1R/M (disp-lo),(disp-hi) FMUL short-real
7773 D8 1101 1000 MOD01 0R/M (disp-lo),(disp-hi) FCOM short-real
7774 D8 1101 1000 MOD01 1R/M (disp-lo),(disp-hi) FCOMP short-real
7775 D8 1101 1000 MOD10 0R/M (disp-lo),(disp-hi) FSUB short-real
7776 D8 1101 1000 MOD10 1R/M (disp-lo),(disp-hi) FSUBR short-real
7777 D8 1101 1000 MOD11 0R/M (disp-lo),(disp-hi) FDIV short-real
7778 D8 1101 1000 MOD11 1R/M (disp-lo),(disp-hi) FDIVR short-real
7779 D8 1101 1000 1100 0REG FADD ST,ST(i)
7780 D8 1101 1000 1100 1REG FMUL ST,ST(i)
7781 D8 1101 1000 1101 0REG FCOM ST(i)
7782 D8 1101 1000 1101 1REG FCOMP ST(i)
7783 D8 1101 1000 1110 0REG FSUB ST,ST(i)
7784 D8 1101 1000 1110 1REG FSUBR ST,ST(i)
7785 D8 1101 1000 1111 0REG FDIV ST,ST(i)
7786 D8 1101 1000 1111 1REG FDIVR ST,ST(i)
7787 D9 1101 1001 MOD00 0R/M (disp-lo),(disp-hi) FLD short-real
7788 D9 1101 1001 MOD00 1R/M reserved
7789 D9 1101 1001 MOD01 0R/M (disp-lo),(disp-hi) FST short-real
7790 D9 1101 1001 MOD01 1R/M (disp-lo),(disp-hi) FSTP short-real
7791 D9 1101 1001 MOD10 0R/M (disp-lo),(disp-hi) FLDENV 14-bytes
7792 D9 1101 1001 MOD10 1R/M (disp-lo),(disp-hi) FLDCW 2-bytes
7793 D9 1101 1001 MOD11 0R/M (disp-lo),(disp-hi) FSTENV 14-bytes
7794 D9 1101 1001 MOD11 1R/M (disp-lo),(disp-hi) FSTCW 2-bytes
7795 D9 1101 1001 1100 0REG FLD ST(i)
7796 D9 1101 1001 1100 1REG FXCH ST(i)
7797 D9 1101 1001 1101 0000 FNOP
7798 D9 1101 1001 1101 0001 reserved
7799 D9 1101 1001 1101 001- reserved
7800 D9 1101 1001 1101 01-- reserved
7801 D9 1101 1001 1101 1REG (1)
7802 The marked encodings are not generated by the language translators. If,
7803 however, the 80287 encounters one of these encodings in the instruction
7804 stream, it will execute it as follows: FSTP ST(i)
7808 D9 1101 1001 1110 0000 FCHS
7809 D9 1101 1001 1110 0001 FABS
7810 D9 1101 1001 1110 001- reserved
7811 D9 1101 1001 1110 0100 FTST
7812 D9 1101 1001 1110 0101 FXAM
7813 D9 1101 1001 1110 011- reserved
7814 D9 1101 1001 1110 1000 FLD1
7815 D9 1101 1001 1110 1001 FLDL2T
7816 D9 1101 1001 1110 1010 FLDL2E
7817 D9 1101 1001 1110 1011 FLDPI
7818 D9 1101 1001 1110 1100 FLDLG2
7819 D9 1101 1001 1110 1101 FLDLN2
7820 D9 1101 1001 1110 1110 FLDZ
7821 D9 1101 1001 1110 1111 reserved
7822 D9 1101 1001 1111 0000 F2XM1
7823 D9 1101 1001 1111 0001 FYL2X
7824 D9 1101 1001 1111 0010 FPTAN
7825 D9 1101 1001 1111 0011 FPATAN
7826 D9 1101 1001 1111 0100 FXTRACT
7827 D9 1101 1001 1111 0101 reserved
7828 D9 1101 1001 1111 0110 FDECSTP
7829 D9 1101 1001 1111 0111 FINCSTP
7830 D9 1101 1001 1111 1000 FPREM
7831 D9 1101 1001 1111 1001 FYL2XP1
7832 D9 1101 1001 1111 1010 FSQRT
7833 D9 1101 1001 1111 1011 reserved
7834 D9 1101 1001 1111 1100 FRNDINT
7835 D9 1101 1001 1111 1101 FSCALE
7836 D9 1101 1001 1111 111- reserved
7837 DA 1101 1010 MOD00 0R/M (disp-lo),(disp-hi) FIADD short-integer
7838 DA 1101 1010 MOD00 1R/M (disp-lo),(disp-hi) FIMUL short-integer
7839 DA 1101 1010 MOD01 0R/M (disp-lo),(disp-hi) FICOM short-integer
7840 DA 1101 1010 MOD01 1R/M (disp-lo),(disp-hi) FICOMP short-integer
7841 DA 1101 1010 MOD10 0R/M (disp-lo),(disp-hi) FISUB short-integer
7842 DA 1101 1010 MOD10 1R/M (disp-lo),(disp-hi) FISUBR short-integer
7843 DA 1101 1010 MOD11 0R/M (disp-lo),(disp-hi) FIDIV short-integer
7844 DA 1101 1010 MOD11 1R/M (disp-lo),(disp-hi) FIDIVR short-integer
7845 DA 1101 1010 11-- ---- reserved
7846 DB 1101 1011 MOD00 0R/M (disp-lo),(disp-hi) FILD short-integer
7847 DB 1101 1011 MOD00 1R/M (disp-lo),(disp-hi) reserved
7848 DB 1101 1011 MOD01 0R/M (disp-lo),(disp-hi) FIST short-integer
7849 DB 1101 1011 MOD01 1R/M (disp-lo),(disp-hi) FISTP short-integer
7850 DB 1101 1011 MOD10 0R/M (disp-lo),(disp-hi) reserved
7851 DB 1101 1011 MOD10 1R/M (disp-lo),(disp-hi) FLD temp-real
7852 DB 1101 1011 MOD11 0R/M (disp-lo),(disp-hi) reserved
7853 DB 1101 1011 MOD11 1R/M (disp-lo),(disp-hi) FSTP temp-real
7854 DB 1101 1011 110- ---- reserved
7855 DB 1101 1011 1110 0000 reserved (8087 FENI)
7856 DB 1101 1011 1110 0001 reserved (8087 FDISI)
7857 DB 1101 1011 1110 0010 FCLEX
7858 DB 1101 1011 1110 0011 FINIT
7859 DB 1101 1011 1110 0100 FSETPM
7860 DB 1101 1011 1110 1--- reserved
7861 DB 1101 1011 1111 ---- reserved
7862 DC 1101 1100 MOD00 0R/M (disp-lo),(disp-hi) FADD long-real
7863 DC 1101 1100 MOD00 1R/M (disp-lo),(disp-hi) FMUL long-real
7864 DC 1101 1100 MOD01 0R/M (disp-lo),(disp-hi) FCOM long-real
7865 DC 1101 1100 MOD01 1R/M (disp-lo),(disp-hi) FCOMP long-real
7866 DC 1101 1100 MOD10 0R/M (disp-lo),(disp-hi) FSUB long-real
7867 DC 1101 1100 MOD10 1R/M (disp-lo),(disp-hi) FSUBR long-real
7868 DC 1101 1100 MOD11 0R/M (disp-lo),(disp-hi) FDIV long-real
7869 DC 1101 1100 MOD11 1R/M (disp-lo),(disp-hi) FDIVR long-real
7870 DC 1101 1100 1100 0REG FADD ST(i),ST
7871 DC 1101 1100 1100 1REG FMUL ST(i),ST
7872 DC 1101 1100 1101 0REG (2)
7873 The marked encodings are not generated by the language translators. If,
7874 however, the 80287 encounters one of these encodings in the instruction
7875 stream, it will execute it as follows: FCOM ST(i)
7879 DC 1101 1100 1101 1REG (3)
7880 The marked encodings are not generated by the language translators. If,
7881 however, the 80287 encounters one of these encodings in the instruction
7882 stream, it will execute it as follows: FCOMP ST(i)
7886 DC 1101 1100 1110 0REG FSUB ST(i),ST
7887 DC 1101 1100 1110 1REG FSUBR ST(i),ST
7888 DC 1101 1100 1111 0REG FDIV ST(i),ST
7889 DC 1101 1100 1111 1REG FDIVR ST(i),ST
7890 DD 1101 1101 MOD00 0R/M (disp-lo),(disp-hi) FLD long-real
7891 DD 1101 1101 MOD00 1R/M reserved
7892 DD 1101 1101 MOD01 0R/M (disp-lo),(disp-hi) FST long-real
7893 DD 1101 1101 MOD01 1R/M (disp-lo),(disp-hi) FSTP long-real
7894 DD 1101 1101 MOD10 0R/M (disp-lo),(disp-hi) FRSTOR 94-bytes
7895 DD 1101 1101 MOD10 1R/M (disp-lo),(disp-hi) reserved
7896 DD 1101 1101 MOD11 0R/M (disp-lo),(disp-hi) FSAVE 94-bytes
7897 DD 1101 1101 MOD11 1R/M (disp-lo),(disp-hi) FSTSW 2-bytes
7898 DD 1101 1101 1100 0REG FFREE ST(i)
7899 DD 1101 1101 1100 1REG (4)
7900 The marked encodings are not generated by the language translators. If,
7901 however, the 80287 encounters one of these encodings in the instruction
7902 stream, it will execute it as follows: FXCH ST(i)
7906 DD 1101 1101 1101 0REG FST ST(i)
7907 DD 1101 1101 1101 1REG FSTP ST(i)
7908 DD 1101 1101 111- ---- reserved
7909 DE 1101 1110 MOD00 0R/M (disp-lo),(disp-hi) FIADD word-integer
7910 DE 1101 1110 MOD00 1R/M (disp-lo),(disp-hi) FIMUL word-integer
7911 DE 1101 1110 MOD01 0R/M (disp-lo),(disp-hi) FICOM word-integer
7912 DE 1101 1110 MOD01 1R/M (disp-lo),(disp-hi) FICOMP word-integer
7913 DE 1101 1110 MOD10 0R/M (disp-lo),(disp-hi) FISUB word-integer
7914 DE 1101 1110 MOD10 1R/M (disp-lo),(disp-hi) FISUBR word-integer
7915 DE 1101 1110 MOD11 0R/M (disp-lo),(disp-hi) FIDIV word-integer
7916 DE 1101 1110 MOD11 1R/M (disp-lo),(disp-hi) FIDIVR word-integer
7917 DE 1101 1110 1100 0REG FADDP ST(i),ST
7918 DE 1101 1110 1100 1REG FMULP ST(i),ST
7919 DE 1101 1110 1101 0--- (5)
7920 The marked encodings are not generated by the language translators. If,
7921 however, the 80287 encounters one of these encodings in the instruction
7922 stream, it will execute it as follows: FCOMP ST(i)
7926 DE 1101 1110 1101 1000 reserved
7927 DE 1101 1110 1101 1001 FCOMPP
7928 DE 1101 1110 1101 101- reserved
7929 DE 1101 1110 1101 11-- reserved
7930 DE 1101 1110 1110 0REG FSUBP ST(i),ST
7931 DE 1101 1110 1110 1REG FSUBRP ST(i),ST
7932 DE 1101 1110 1111 0REG FDIVP ST(i),ST
7933 DE 1101 1110 1111 1REG FDIVRP ST(i),ST
7934 DF 1101 1111 MOD00 0R/M (disp-lo),(disp-hi) FILD word-integer
7935 DF 1101 1111 MOD00 1R/M (disp-lo),(disp-hi) reserved
7936 DF 1101 1111 MOD01 0R/M (disp-lo),(disp-hi) FIST word-integer
7937 DE 1101 1110 MOD01 1R/M (disp-lo),(disp-hi) FISTP word-integer
7938 DF 1101 1111 MOD10 0R/M (disp-lo),(disp-hi) FBLD packed-decimal
7939 DF 1101 1111 MOD10 1R/M (disp-lo),(disp-hi) FILD long-integer
7940 DF 1101 1111 MOD11 0R/M (disp-lo),(disp-hi) FBSTP packed-decimal
7941 DF 1101 1111 MOD11 1R/M (disp-lo),(disp-hi) FISTP long-integer
7942 DF 1101 1111 1100 0REG (6)
7943 The marked encodings are not generated by the language translators. If,
7944 however, the 80287 encounters one of these encodings in the instruction
7945 stream, it will execute it as follows: FFREE ST(i) and pop stack
7949 DF 1101 1111 1100 1REG (7)
7950 The marked encodings are not generated by the language translators. If,
7951 however, the 80287 encounters one of these encodings in the instruction
7952 stream, it will execute it as follows: FXCH ST(i)
7956 DF 1101 1111 1101 0REG (8)
7957 The marked encodings are not generated by the language translators. If,
7958 however, the 80287 encounters one of these encodings in the instruction
7959 stream, it will execute it as follows: FSTP ST(i)
7963 DF 1101 1111 1101 1REG (9)
7964 The marked encodings are not generated by the language translators. If,
7965 however, the 80287 encounters one of these encodings in the instruction
7966 stream, it will execute it as follows: FSTP ST(i)
7970 DF 1101 1111 1110 000 FSTSW AX
7971 DF 1101 1111 1111 XXX reserved
7974 Appendix B Compatibility Between the 80287 NPX and the 8087
7976 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7978 The 80286/80287 operating in Real-Address mode will execute 8087 programs
7979 without major modification. However, because of differences in the handling
7980 of numeric exceptions by the 80287 NPX and the 8087 NPX, exception-handling
7981 routines may need to be changed.
7983 This appendix summarizes the differences between the 80287 NPX and the 8087
7984 NPX, and provides details showing how 8087 programs can be ported to the
7987 1. The 80287 signals exceptions through a dedicated ERROR line to the
7988 80286. The 80287 error signal does not pass through an interrupt
7989 controller (the 8087 INT signal does). Therefore, any
7990 interrupt-controller-oriented instructions in numeric exception
7991 handlers for the 8087 should be deleted.
7993 2. The 8087 instructions FENI/FNENI and FDISI/FNDISI perform no useful
7994 function in the 80287. If the 80287 encounters one of these opcodes in
7995 its instruction stream, the instruction will effectively be ignored‘‘
7996 none of the 80287 internal states will be updated. While 8087 code
7997 containing these instructions may be executed on the 80287, it is
7998 unlikely that the exception-handling routines containing these
7999 instructions will be completely portable to the 80287.
8001 3. Interrupt vector 16 must point to the numeric exception handling
8004 4. The ESC instruction address saved in the 80287 includes any leading
8005 prefixes before the ESC opcode. The corresponding address saved in the
8006 8087 does not include leading prefixes.
8008 5. In Protected-Address mode, the format of the 80287's saved
8009 instruction and address pointers is different than for the 8087. The
8010 instruction opcode is not saved in Protected mode‘‘exception handlers
8011 will have to retrieve the opcode from memory if needed.
8013 6. Interrupt 7 will occur in the 80286 when executing ESC instructions
8014 with either TS (task switched) or EM (emulation) of the 80286 MSW set
8015 (TS = 1 or EM = 1). If TS is set, then a WAIT instruction will also
8016 cause interrupt 7. An exception handler should be included in 80287
8017 code to handle these situations.
8019 7. Interrupt 9 will occur if the second or subsequent words of a
8020 floating-point operand fall outside a segment's size. Interrupt 13
8021 will occur if the starting address of a numeric operand falls outside
8022 a segment's size. An exception handler should be included in 80287
8023 code to report these programming errors.
8025 8. Except for the processor control instructions, all of the 80287
8026 numeric instructions are automatically synchronized by the 80286 CPU‘‘
8027 the 80286 automatically tests the BUSY line from the 80287 to ensure
8028 that the 80287 has completed its previous instruction before executing
8029 the next ESC instruction. No explicit WAIT instructions are required
8030 to assure this synchronization. For the 8087 used with 8086 and 8088
8031 processors, explicit WAITs are required before each numeric
8032 instruction to ensure synchronization. Although 8087 programs having
8033 explicit WAIT instructions will execute perfectly on the 80287 without
8034 reassembly, these WAIT instructions are unnecessary.
8036 9. Since the 80287 does not require WAIT instructions before each
8037 numeric instruction, the ASM286 assembler does not automatically
8038 generate these WAIT instructions. The ASM86 assembler, however,
8039 automatically precedes every ESC instruction with a WAIT instruction.
8040 Although numeric routines generated using the ASM86 assembler will
8041 generally execute correctly on the 80286/20, reassembly using ASM286
8042 may result in a more compact code image.
8044 The processor control instructions for the 80287 may be coded using
8045 either a WAIT or No-WAIT form of mnemonic. The WAIT forms of these
8046 instructions cause ASM286 to precede the ESC instruction with a
8047 CPU WAIT instruction, in the identical manner as does ASM86.
8049 10. A recommended way to detect the presence of an 80287 in an 80286
8050 system (or an 8087 in an 8086 system) is shown below. It assumes that
8051 the sytem hardware causes the data bus to be high if no 80287 is
8052 present to drive the data lines during the FSTSW (Store 80287 Status
8055 FND_287: FNINIT ; initialize numeric processor.
8056 FSTSTW STAT ; store status word into location
8059 OR AL,AL ; Zero Flag reflects result of OR.
8060 JZ GOT_287 ; Zero in AL means 80287 is present.
8065 OR AX,0004H ; set EM bit in Machine Status Word.
8066 LMSW AX ; to enable software emulation of 287.
8069 ; 80287 is present in system
8072 OR AX,0002H ; set MP bit in Machine Status Word
8073 LMSW AX ; to permit normal 80287 operation
8077 CONTINUE: ; and off we go
8079 An 80286/80287 design must place a pullup resistor on one of the low
8080 eight data bus bits of the 80286 to be sure it is read as a high when
8081 no 80287 is present.
8084 Appencix C Implementing the IEEE P754 Standard
8086 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8088 The 80287 NPX and standard support library software, provides an
8089 implementation of the IEEE "A Proposed Standard for Binary Floating-Point
8090 Arithmetic," Draft 10.0, Task P754, of December 2, 1982. The 80287 Support
8091 Library, described in 80287 Support Library Reference Manual, Order Number
8092 122129, is an example of such a support library.
8094 This appendix describes the relationship between the 80287 NPX and the IEEE
8095 Standard. Where the Standard has options, Intel's choices in implementing
8096 the 80287 are described. Where portions of the Standard are implemented
8097 through software, this appendix indicates which modules of the 80287 Support
8098 Library implement the Standard. Where special software in addition to the
8099 Support Library may be required by your application, this appendix indicates
8100 how to write this software.
8102 This appendix contains many terms with precise technical meanings,
8103 specified in the 754 Standard. Where these terms are used, they have been
8104 capitalized to emphasize the precision of their meanings. The Glossary
8105 provides the definitions for all capitalized phrases in this appendix.
8108 Options Implemented in the 80287
8109 The 80287 SHORT_REAL and LONG_REAL formats conform precisely to the
8110 Standard's Single and Double Floating-Point Numbers, respectively. The 80287
8111 TEMP_REAL format is the same as the Standard's Double Extended format. The
8112 Standard allows a choice of Bias in representing the exponent; the 80287
8113 uses the Bias 16383 decimal.
8115 For the Double Extended format, the Standard contains an option for the
8116 meaning of the minimum exponent combined with a nonzero significand. The
8117 Bias for this special case can be either 16383, as in all the other cases,
8118 or 16382, making the smallest exponent equivalent to the second-smallest
8119 exponent. The 80287 uses the Bias 16382 for this case. This allows the 80287
8120 to distinguish between Denormal numbers (integer part is zero, fraction is
8121 nonzero, Biased exponent is 0) and Unnormal numbers of the same value (same
8122 as the denormal except the Biased Exponent is 1).
8124 The Standard allows flexibility in specifying which NaNs are trapping and
8125 which are nontrapping. The EH287.LIB module of the 80287 Support Library
8126 provides a software implementation of nontrapping NaNs, and defines one
8127 distinction between trapping and nontrapping NaNs: If the most significant
8128 bit of the fractional part of a NaN is 1, the NaN is nontrapping. If it is
8129 0, the NaN is trapping.
8131 When a masked Invalid Operation error involves two NaN inputs, the Standard
8132 allows flexibility in choosing which NaN is output. The 80287 selects the
8133 NaN whose absolute value is greatest.
8136 Areas of the Standard Implemented in Software
8137 There are five areas of the Standard that are not implemented directly in
8138 the 80287 hardware; these areas are instead implemented in software as part
8139 of the 80287 Support Library.
8141 1. The Standard requires that a Normalizing Mode be provided, in which
8142 any nonnormal operands to functions are automatically normalized
8143 before the function is performed. The NPX provides a "Denormal
8144 operand" exception for this case, allowing the exception handler
8145 the opportunity to perform the normalization specified by the
8146 Standard. The Denormal operand exception handler provided by
8147 EH287.LIB implements the Standard's Normalizing Mode completely for
8148 Single- and Double-precision arguments. Normalizing mode for Double
8149 Extended operands is implemented in EH287.LIB with one non-Standard
8150 feature, discussed in the next section.
8152 2. The Standard specifies that in comparing two operands whose
8153 relationship is "unordered," the equality test yield an answer of
8154 FALSE, with no errors or exceptions. The 80287 FCOM and FTST
8155 instructions themselves issue an Invalid Operation exception in this
8156 case. The error handler EH287.LIB filters out this Invalid Operation
8157 error using the following convention: Whenever an FCOM or FTST
8158 instruction is followed by a MOV AX,AX instruction (8BC0 Hex), and
8159 neither argument is a trapping NaN, the error handler will assume that
8160 a Standard equality comparison was intended, and return the correct
8161 answer with the Invalid Operation exception flag erased. Note that the
8162 Invalid Operation exception must be unmasked for this action to
8165 3. The Standard requires that two kinds of NaN's be provided: trapping
8166 and nontrapping. Nontrapping NaNs will not cause further Invalid
8167 Operation errors when they occur as operands to calculations. The NPX
8168 hardware directly supports only trapping NaN's; the EH287.LIB
8169 software implements nontrapping NaNs by returning the correct answer
8170 with the Invalid Operation exception flag erased. Note that the
8171 Invalid Operation exception must be unmasked for this action to occur.
8173 4. The Standard requires that all functions that convert real numbers to
8174 integer formats automatically normalize the inputs if necessary. The
8175 integer conversion functions contained in CEL287.LIB fully meet the
8176 Standard in this respect; the 80287 FIST instruction alone does not
8177 perform this normalization.
8179 5. The Standard specifies the remainder function which is provided by
8180 mqerRMD in CEL287.LIB. The 80287 FPREM instruction returns answers
8181 within a different range.
8184 Additional Software to Meet the Standard
8185 There are two cases in which additional software is required in conjunction
8186 with the 80287 Support Library in order to meet the standard. The 80287
8187 Support Library does not provide this software in the interest of saving
8188 space and because the vast majority of applications will never encounter
8191 1. When the Invalid Operation exception is masked, Nontrapping NaNs are
8192 not implemented fully. Likewise, the Standard's equality test for
8193 "unordered" operands is not implemented when the Invalid Operation
8194 exception is masked. Programmers can simulate the Standard notion of
8195 a masked Invalid Operation exception by unmasking the 80287 Invalid
8196 Operation exception, and providing an Invalid Operation exception
8197 handler that supports nontrapping NaNs and the equality test, but
8198 otherwise acts just as if the Invalid Operation exception were
8199 masked. The 80287 Support Library Reference Manual contains examples
8200 for programming this handler in both ASM286 andPL/M-286.
8202 2. In Normalizing Mode, Denormal operands in the TEMP_REAL format are
8203 converted to 0 by EH287.LIB, giving sharp Underflow to 0. The Standard
8204 specifies that the operation be performed on the real numbers
8205 represented by the denormals, giving gradual underflow. To correctly
8206 perform such arithmetic while in Normalizing Mode, programmers would
8207 have to normalize the operands into a format identical to TEMP_REAL
8208 except for two extra exponent bits, then perform the operation on
8209 those numbers. Thus, software must be written to handle the 17-bit
8210 exponent explicitly.
8212 In designing the EH287.LIB, it was felt that it would be a disadvantage to
8213 most users to increase the size of the Normalizing routine by the amount
8214 necessary to provide this expanded arithmetic. Because the TEMP_REAL
8215 exponent field is so much larger than the LONG_REAL exponent field, it is
8216 extremely unlikely that TEMP_REAL underflow will be encountered in most
8219 If meeting the Standard is a more important criterion for your application
8220 than the choice between Normalizing and warning modes, then you can select
8221 warning mode (Denormal operand exceptions masked), which fully meets the
8224 If you do wish to implement the Normalization of denormal operands in
8225 TEMP_REAL format using extra exponent bits, the list below indicates some
8226 useful pointers about handling Denormal operand exceptions:
8228 1. TEMP_REAL numbers are considered Denormal by the NPX whenever the
8229 Biased Exponent is 0 (minimum exponent). This is true even if the
8230 explicit integer bit of the significand is 1. Such numbers can occur
8231 as the result of Underflow.
8233 2. The 80287 FLD instruction can cause a Denormal Operand error if a
8234 number is being loaded from memory. It will not cause this exception
8235 if the number is being loaded from elsewhere in the 80287 stack.
8237 3. The 80287 FCOM and FTST instructions will cause a Denormal Operand
8238 exception for unnormal operands as well as for denormal operands.
8240 4. In cases where both the Denormal Operand and Invalid Operation
8241 exceptions occur, you will want to know which is signalled first. When
8242 a comparison instruction operates between a nonexistent stack element
8243 and a denormal number in 80286 memory, the D and I exceptions are
8244 issued simultaneously. In all other situations, a Denormal Operand
8245 exception takes precedence over a nonstack Invalid operation
8246 exception, while a stack Invalid Operation exception takes precedence
8247 over a Denormal Operand exception.
8250 Glossary of 80287 and Floating-Point Terminology
8252 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8254 This glossary defines many terms that have precise technical meanings as
8255 specified in the IEEE 754 Standard. Where these terms are used, they have
8256 been capitalized to emphasize the precision of their meanings.
8259 a state of the 80287, selected in the 80287 Control Word, in which
8260 infinities are treated as having a sign. Thus, the values +INFINITY and
8261 -INFINITY are considered different; they can be compared with finite
8262 numbers and with each other.
8265 (1) a term used in logarithms and exponentials. In both contexts, it is
8266 a number that is being raised to a power. The two equations (y = log
8267 base b of x) and (b^(y) = x) are the same.
8270 (2) a number that defines the representation being used for a string of
8271 digits. Base 2 is the binary representation; Base 10 is the decimal
8272 representation; Base 16 is the hexadecimal representation. In each case,
8273 the Base is the factor of increased significance for each succeeding
8274 digit (working up from the bottom).
8277 the difference between the unsigned Integer that appears in the Exponent
8278 field of a Floating-Point Number and the true Exponent that it
8279 represents. To obtain the true Exponent, you must subtract the Bias from
8280 the given Exponent. For example, the Short Real format has a Bias of 127
8281 whenever the given Exponent is nonzero. If the 8-bit Exponent field
8282 contains 10000011, which is 131, the true Exponent is 131-127, or +4.
8285 the Exponent as it appears in a Floating-Point Number, interpreted as an
8286 unsigned, positive number. In the above example, 131 is the Biased
8289 Binary Coded Decimal:
8290 a method of storing numbers that retains a base 10 representation. Each
8291 decimal digit occupies 4 full bits (one hexadecimal digit). The hex
8292 values A through F (1010 through 1111) are not used. The 80287 supports
8293 a Packed Decimal format that consists of 9 bytes of Binary Coded Decimal
8294 (18 decimal digits) and one sign byte.
8297 an entity just like a decimal point, except that it exists in binary
8298 numbers. Each binary digit to the right of the Binary Point is
8299 multiplied by an increasing negative power of two.
8302 the four "condition code" bits of the 80287 Status Word. These bits are
8303 set to certain values by the compare, test, examine, and remainder
8304 functions of the 80287.
8307 a term used for some non-Intel computers, meaning the Exponent field of
8308 a Floating-Point Number.
8311 to set the fractional part of a real number to zero, yielding the
8312 nearest integer in the direction of zero.
8315 a 16-bit 80287 register that the user can set, to determine the modes of
8316 computation the 80287 will use, and the error interrupts that will be
8320 a special form of Floating-Point Number, produced when an Underflow
8321 occurs. On the 80287, a Denormal is defined as a number with a Biased
8322 Exponent that is zero. By providing a Significand with leading zeros,
8323 the range of possible negative Exponents can be extended by the number
8324 of bits in the Significand. Each leading zero is a bit of lost accuracy,
8325 so the extended Exponent range is obtained by reducing significance.
8328 the Standard's term for the 80287 Temporary Real format, with more
8329 Exponent and Significand bits than the Double (Long Real) format, and an
8330 explicit Integer bit in the Significand.
8332 Double Floating Point Number:
8333 the Standard's term for the 80287's 64-bit Long Real format.
8336 the 14 bytes of 80287 registers affected by the FSTENV and FLDENV
8337 instructions. It encompasses the entire state of the 80287, except for
8338 the 8 Temporary Real numbers of the 80287 stack. Included are the
8339 Control Word, Status Word, Tag Word, and the instruction, opcode, and
8340 operand information provided by interrupts.
8343 any of the six error conditions (I, D, O, U, Z, P) signalled by the
8347 (1) any power that is raised by an exponential function. For example,
8348 the operand to the function mqerEXP is an Exponent. The Integer operand
8349 to mqerYI2 is an Exponent.
8352 (2) the field of a Floating-Point Number that indicates the magnitude of
8353 the number. This would fall under the above more general definition (1),
8354 except that a Bias sometimes needs to be subtracted to obtain the
8357 Floating-Point Number:
8358 a sequence of data bytes that, when interpreted in a standardized way,
8359 represents a Real number. Floating-Point Numbers are more versatile than
8360 Integer representations in two ways. First, they include fractions.
8361 Second, their Exponent parts allow a much wider range of magnitude than
8362 possible with fixed-length Integer representations.
8365 a method of handling the Underflow error condition that minimizes the
8366 loss of accuracy in the result. If there is a Denormal number that
8367 represents the correct result, that Denormal is returned. Thus, digits
8368 are lost only to the extent of denormalization. Most computers return
8369 zero when Underflow occurs, losing all significant digits.
8371 Implicit Integer Bit:
8372 a part of the Significand in the Short Real and Long Real formats that
8373 is not explicitly given. In these formats, the entire given Significand
8374 is considered to be to the right of the Binary Point. A single Implicit
8375 Integer Bit to the left of the Binary Point is always 1, except in one
8376 case. When the Exponent is the minimum (Biased Exponent is 0), the
8377 Implicit Integer Bit is 0.
8380 a special value that is returned by functions when the inputs are such
8381 that no other sensible answer is possible. For each Floating-Point
8382 format there exists one Nontrapping NaN that is designated as the
8383 Indefinite value. For binary Integer formats, the negative number
8384 furthest from zero is often considered the Indefinite value. For the
8385 80287 Packed Decimal format, the Indefinite value contains all 1's in
8386 the sign byte and the uppermost digits byte.
8389 a value that has greater magnitude than any Integer or any Real number.
8390 The existence of Infinity is subject to heated philosophical debate.
8391 However, it is often useful to consider Infinity as another number,
8392 subject to special rules of arithmetic. All three Intel Floating-Point
8393 formats provide representations for +INFINITY and -INFINITY. They
8394 support two ways of dealing with Infinity: Projective (unsigned) and
8398 a number (positive, negative, or zero) that is finite and has no
8399 fractional part. Integer can also mean the computer representation for
8400 such a number: a sequence of data bytes, interpreted in a standard way.
8401 It is perfectly reasonable for Integers to be represented in a
8402 Floating-Point format; this is what the 80287 does whenever an Integer is
8403 pushed onto the 80287 stack.
8406 the error condition for the 80287 that covers all cases not covered by
8407 other errors. Included are 80287 stack overflow and underflow, NaN
8408 inputs, illegal infinite inputs, out-of-range inputs, and illegal
8412 an Integer format supported by the 80287 that consists of a 64-bit Two's
8413 Complement quantity.
8416 a Floating-Point Format supported by the 80287 that consists of a sign,
8417 an 11-bit Biased Exponent, an Implicit Integer Bit, and a 52-bit
8418 Significand‘‘a total of 64 explicit bits.
8421 a term used for some non-Intel computers, meaning the Significand of a
8422 Floating-Point Number.
8425 a term that applies to each of the six 80287 Exceptions I,D,Z,O,U,P. An
8426 exception is Masked if a corresponding bit in the 80287 Control Word is
8427 set to 1. If an exception is Masked, the 80287 will not generate an
8428 interrupt when the error condition occurs; it will instead provide its
8432 an abbreviation for Not a Number; a Floating-Point quantity that does
8433 not represent any numeric or infinite quantity. NaNs should be returned
8434 by functions that encounter serious errors. If created during a sequence
8435 of calculations, they are transmitted to the final answer and can
8436 contain information about where the error occurred.
8439 a NaN in which the most significant bit of the fractional part of the
8440 Significand is 1. By convention, these NaNs can undergo certain
8441 operations without visible error. Nontrapping NaNs are implemented for
8442 the 80287 via the software in EH87.LIB.
8445 the representation of a number in a Floating-Point format in which the
8446 Significand has an Integer bit 1 (either explicit or Implicit).
8449 a state in which nonnormal inputs are automatically converted to normal
8450 inputs whenever they are used in arithmetic. Normalizing Mode is
8451 implemented for the 80287 via the software in EH87.LIB.
8454 Numeric Processor Extension. This is the 80287.
8457 an error condition in which the correct answer is finite, but has
8458 magnitude too great to be represented in the destination format.
8461 an Integer format supported by the 80287. A Packed Decimal number is a
8462 10-byte quantity, with nine bytes of 18 Binary Coded Decimal digits, and
8463 one byte for the sign.
8466 to remove from a stack the last item that was placed on the stack.
8469 an option, programmed through the 80287 Control Word, that allows all
8470 80287 arithmetic to be performed with reduced precision. Because no
8471 speed advantage results from this option, its only use is for strict
8472 compatibility with the IEEE Standard, and with other computer
8475 Precision Exception:
8476 an 80287 error condition that results when a calculation does not return
8477 an exact answer. This exception is usually Masked and ignored; it is
8478 used only in extremely critical applications, when the user must know if
8479 the results are exact.
8482 a state of the 80287, selected in the 80287 Control Word, in which
8483 infinities are treated as not having a sign. Thus the values +INFINITY
8484 and -INFINITY are considered the same. Certain operations, such as
8485 comparison to finite numbers, are illegal in Projective Mode but legal
8486 in Affine Mode. Thus Projective Mode gives you a greater degree of error
8487 control over infinite inputs.
8490 a special value of the Temporary Real format. It is a number with a zero
8491 significand and an Exponent that is neither all zeros or all ones.
8492 Pseudo zeros can come about as the result of multiplication of two
8493 Unnormal numbers; but they are very rare.
8496 any finite value (negative, positive, or zero) that can be represented
8497 by a decimal expansion. The fractional part of the decimal expansion can
8498 contain an infinite number of digits. Reals can be represented as the
8499 points of a line marked off like a ruler. The term Real can also refer
8500 to a Floating-Point Number that represents a Real value.
8503 an Integer format supported by the 80287 that consists of a 32-bit Two's
8504 Complement quantity. Short Integer is not the shortest 80287 Integer
8505 format‘‘the 16-bit Word Integer is.
8508 a Floating-Point Format supported by the 80287, which consists of a
8509 sign, an 8-bit Biased Exponent, an Implicit Integer Bit, and a 23-bit
8510 Significand‘‘a total of 32 explicit bits.
8513 the part of a Floating-Point Number that consists of the most
8514 significant nonzero bits of the number, if the number were written out
8515 in an unlimited binary format. The Significand alone is considered to
8516 have a Binary Point after the first (possibly Implicit) bit; the Binary
8517 Point is then moved according to the value of the Exponent.
8520 a Floating-Point format, required by the Standard, that provides greater
8521 precision than Single; it also provides an explicit Integer Significand
8522 bit. The 80287's Temporary Real format meets the Single Extended
8523 requirement as well as the Double Extended requirement.
8525 Single Floating-Point Number:
8526 the Standard's term for the 80287's 32-bit Short Real format.
8529 "a Proposed Standard for Binary Floating-Point Arithmetic," Draft 10.0
8530 of IEEE Task P754, December 2, 1982.
8533 A 16-bit 80287 register that can be manually set, but which is usually
8534 controlled by side effects to 80287 instructions. It contains condition
8535 codes, the 80287 stack pointer, busy and interrupt bits, and error
8539 a 16-bit 80287 register that is automatically maintained by the 80287.
8540 For each space in the 80287 stack, it tells if the space is occupied by
8541 a number; if so, it gives information about what kind of number.
8544 the main Floating-Point Format used by the 80287. It consists of a sign,
8545 a 15-bit Biased Exponent, and a Significand with an explicit Integer bit
8546 and 63 fractional-part bits.
8549 one of a class of functions for which polynomial formulas are always
8550 approximate, never exact for more than isolated values. The 80287
8551 supports trigonometric, exponential, and logarithmic functions; all are
8555 a NaN that causes an I error whenever it enters into a calculation or
8556 comparison, even a nonordered comparison.
8559 a method of representing Integers. If the uppermost bit is 0, the number
8560 is considered positive, with the value given by the rest of the bits. If
8561 the uppermost bit is 1, the number is negative, with the value obtained
8562 by subtracting (2^(bit count)) from all the given bits. For example, the
8563 8-bit number 11111100 is -4, obtained by subtracting 2^(8) from 252.
8566 the true value that tells how far and in which direction to move the
8567 Binary Point of the Significand of a Floating-Point Number. For example,
8568 if a Short Real Exponent is 131, we subtract the Bias 127 to obtain the
8569 Unbiased Exponent +4. Thus, the Real number being represented is the
8570 Significand with the Binary Point shifted 4 bits to the right.
8573 an error condition in which the correct answer is nonzero, but has a
8574 magnitude too small to be represented as a Normal number in the
8575 destination Floating-Point format. The Standard specifies that an
8576 attempt be made to represent the number as a Denormal.
8579 a term that applies to each of the six 80287 Exceptions: I,D,Z,O,U,P. An
8580 exception is Unmasked if a corresponding bit in the 80287 Control Word
8581 is set to 0. If an exception is Unmasked, the 80287 will generate an
8582 interrupt when the error condition occurs. You can provide an interrupt
8583 routine that customizes your error recovery.
8586 a Temporary Real representation in which the explicit Integer bit of the
8587 Significand is zero, and the exponent is nonzero. We consider Unnormal
8588 numbers distinct from Denormal numbers.
8591 an Integer format supported by both the 80286 and the 80287 that
8592 consists of a 16-bit Two's Complement quantity.
8595 an error condition in which the inputs are finite, but the correct
8596 answer, even with an unlimited exponent, has infinite magnitude.
8600 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8604 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8607 Arithmetic Instructions
8609 Automatic Exception Handling
8613 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8618 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8619 Comparison Instructions
8620 Compatibility Between the 80287 and 8087
8621 Computation Fundamentals
8622 Concurrent (80286 and 80287) Processing
8623 Condition Codes Interpretation
8624 Constant Instructions
8629 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8630 Data Synchronization
8631 Data Transfer Instructions
8632 Data Types and Formats
8635 Encoding of Data Type
8642 Denormalized Operand
8644 Destination Operands
8648 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8649 EM (Emulation Mode) Bit in 80286
8651 Encoding of Data Types
8652 Error Synchronization
8653 Exception Handling Examples
8654 Exception Handling, Numeric Processing
8656 Automatic Exception Handling
8657 Handling Numeric Errors
8661 Numeric Overflow and Underflow
8662 Software Exception Handling
8668 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8669 F2XM1 (Exponentiation)
8671 FADDP (Add Real and POP)
8672 FABS (Absolute Value)
8673 FBLD (Packed Decimal‘‘BCD‘‘Load)
8674 FBSTP (Packed Decimal‘‘BCD‘‘Store and Pop)
8676 FCLEX/FNCLEX (Clear Exceptions)
8678 FCOMP (Compare Real and Pop)
8679 FCOMPP (Compare Real and Pop Twice)
8680 FDECSTP (Decrement Stack Pointer)
8683 FDIV DWORD PTR (Division, Single Precision)
8684 FDIVP (Divide Real and Pop)
8685 FDIVR (Divide Real Reversed)
8686 FDIVRP (Divide Real Reversed and Pop)
8688 FFREE (Free Register)
8690 FICOM (Integer Compare)
8691 FICOMP (Integer Compare and Pop)
8692 FIDIV (Integer Divide)
8693 FIDIVR (Integer Divide Reversed)
8695 FIMUL (Integer Multiply)
8696 FINCSTP (Increment Stack Pointer)
8697 FINIT/FNINIT (Initialize Processor)
8698 FIST (Integer Store)
8699 FISTP (Integer Store and Pop)
8700 FISUB (Integer Subtract)
8701 FISUBR (Integer Subtract Reversed)
8704 FLDCW (Load Control Word)
8705 FLDENV (Load Environment)
8706 FLDL2E (Load Log Base 2 of e)
8707 FLDL2T (Load Log Base 2 of 10)
8708 FLDLG2 (Load Log Base 3 10 of 2)
8709 FLDLN2 (Load Log Base e of 2)
8712 FMUL (Multiply Real)
8713 FMULP (Multiply Real and Pop)
8715 FPATAN (Partial Arctangant)
8716 FPREM (Partial Remainder)
8717 FPTAN (Partial Tangent)
8718 FRNDINT (Round to Integer)
8719 FRSTOR (Restore State)
8720 FSAVE, FNSAVE (Save State)
8722 FSETPM (Set Protected Mode)
8725 FSTCW/FNSTCW (Store Control Word)
8726 FSTENV/FNSTENV (Store Environment)
8727 FSTP (Store Real and Pop)
8728 FSTSW/FNSTSW (Store Status Word)
8729 FSTSW AX, FNSTSW AX (Store Status Word in AX)
8730 FSUB (Subtract Real)
8731 FSUBP (Subtract Real and Pop)
8732 FSUBR (Subtract Real Reversed)
8733 FSUBRP (Subtract Real Reversed and Pop)
8737 FXCH (Exchange Registers)
8738 FXTRACT (Extract Exponent and Significand)
8739 FYL2X (Logarithm‘‘of x)
8740 FYL2XP1 (Logarithm‘‘of x+1)
8744 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8745 GET$REAL$ERROR (Store, then Clear, Exception Flags)
8749 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8750 Handling Numeric Errors
8755 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8756 I/O Locations (Dedicated and Reserved)
8757 IEEE P754 Standard, Implementation
8762 INIT$REAL$MATH$UNIT (Initialize Processor Procedure)
8763 Initialization and Control
8764 Instruction Coding and Decoding
8765 Instruction Execution Times
8768 Introduction to Numeric Processor 80287
8773 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8779 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8780 Machine Instruction Encoding and Decoding
8782 MP (Math Present) Flag
8786 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8789 Nonnormal Real Numbers
8793 Numeric Overflow and Underflow
8794 Numeric Processor Overview
8798 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8804 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8805 Packed Decimal Notation
8808 Pointers (INstruction/Data)
8809 Processor Control Instructions
8810 Programming Examples,
8812 Conditional Branching
8814 Floating Point to ASCII Conversion
8815 Function Partitioning
8816 Special Instructions
8817 Programming Interface
8818 Pseudo zeros and zeros
8822 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8825 Recognizing the 80287
8827 RESTORE$REAL$STATUS (Restore Processor State)
8832 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8833 SAVE$REAL$STATUS (Save Processor State)
8835 SET$REAL$MODE (Set Exception Masks,Rounding Precision, and Infinity
8837 Short Integer Format
8840 Software Exception Handling
8846 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8848 Temporary Real Format
8849 Transcendental Instructions
8850 Trigonometric Calculation Examples
8854 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8861 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8867 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8871 99""*-\98]PR_:*pRDWFL
\x03^AWJU
\x06FIL
\bSLXEX
\x0elnb
\x17\x0e\x0e\x0f\x1e U
\x01\br
\x17\x16szxu
\x10<
\x13wytx
\x7f3
\x1fzuw|
\x197
\x18~
\f\x1a